@fluencypassdevs/cycle 1.27.0 → 1.27.2
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.
|
@@ -0,0 +1,2937 @@
|
|
|
1
|
+
// GERADO por scripts/build-registry.ts a partir de public/registry.json — NÃO EDITAR À MÃO.
|
|
2
|
+
// Para alterar dados de um componente no MCP, edite o bloco `mcp` do item no registry.json
|
|
3
|
+
// e rode `npx tsx scripts/build-registry.ts`.
|
|
4
|
+
export const COMPONENTS = [
|
|
5
|
+
{
|
|
6
|
+
"name": "Button",
|
|
7
|
+
"import": "import { Button } from \"@fluencypassdevs/cycle\"",
|
|
8
|
+
"description": "Botao com 6 variants (default, destructive, outline, secondary, ghost, link), 8 sizes (xs, sm, default, lg, icon-xs, icon-sm, icon-default, icon-lg). Pressed state (scale+brightness). Touch target 44px (WCAG 2.5.8). Suporte a temas via .theme-*.",
|
|
9
|
+
"props": [
|
|
10
|
+
{
|
|
11
|
+
"name": "variant",
|
|
12
|
+
"type": "\"default\" | \"destructive\" | \"outline\" | \"secondary\" | \"ghost\" | \"link\"",
|
|
13
|
+
"default": "\"default\""
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "size",
|
|
17
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\" | \"icon-xs\" | \"icon-sm\" | \"icon-default\" | \"icon-lg\"",
|
|
18
|
+
"default": "\"default\""
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "asChild",
|
|
22
|
+
"type": "boolean",
|
|
23
|
+
"default": "false"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"example": "<Button variant=\"default\" size=\"sm\">Salvar</Button>\n<Button variant=\"outline\" size=\"lg\">Cancelar</Button>\n<Button variant=\"ghost\" size=\"icon-sm\"><CycleIcon icon={X} size=\"sm\" decorative /></Button>",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"botao",
|
|
29
|
+
"button",
|
|
30
|
+
"cta",
|
|
31
|
+
"acao",
|
|
32
|
+
"submit",
|
|
33
|
+
"click"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "Input",
|
|
38
|
+
"import": "import { Input } from \"@fluencypassdevs/cycle\"",
|
|
39
|
+
"description": "Campo de entrada com 2 variantes (outline, filled), 3 sizes (sm, default, lg). Estados: default, focused, disabled, error (aria-invalid). Suporte a temas via .theme-*.",
|
|
40
|
+
"props": [
|
|
41
|
+
{
|
|
42
|
+
"name": "variant",
|
|
43
|
+
"type": "\"outline\" | \"filled\"",
|
|
44
|
+
"default": "\"outline\""
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "inputSize",
|
|
48
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
49
|
+
"default": "\"default\""
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"example": "<Input placeholder=\"Email\" />\n<Input variant=\"filled\" inputSize=\"lg\" />\n<Input aria-invalid=\"true\" />",
|
|
53
|
+
"keywords": [
|
|
54
|
+
"input",
|
|
55
|
+
"campo",
|
|
56
|
+
"texto",
|
|
57
|
+
"form",
|
|
58
|
+
"formulario",
|
|
59
|
+
"email",
|
|
60
|
+
"senha"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "Sheet",
|
|
65
|
+
"import": "import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter, SheetClose } from \"@fluencypassdevs/cycle\"",
|
|
66
|
+
"description": "Painel deslizante (overlay lateral ou bottom). Sides: top, right, bottom, left.",
|
|
67
|
+
"props": [
|
|
68
|
+
{
|
|
69
|
+
"name": "side",
|
|
70
|
+
"type": "\"top\" | \"right\" | \"bottom\" | \"left\"",
|
|
71
|
+
"default": "\"right\""
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"example": "<Sheet>\n <SheetTrigger asChild><Button>Abrir</Button></SheetTrigger>\n <SheetContent side=\"right\">\n <SheetHeader><SheetTitle>Titulo</SheetTitle></SheetHeader>\n Conteudo\n </SheetContent>\n</Sheet>",
|
|
75
|
+
"keywords": [
|
|
76
|
+
"sheet",
|
|
77
|
+
"drawer",
|
|
78
|
+
"painel",
|
|
79
|
+
"lateral",
|
|
80
|
+
"overlay",
|
|
81
|
+
"menu",
|
|
82
|
+
"sidebar"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "Tabs",
|
|
87
|
+
"import": "import { Tabs, TabsList, TabsTrigger, TabsContent } from \"@fluencypassdevs/cycle\"",
|
|
88
|
+
"description": "Componente de abas com 2 variants (default, line), orientacao horizontal e vertical.",
|
|
89
|
+
"props": [
|
|
90
|
+
{
|
|
91
|
+
"name": "variant",
|
|
92
|
+
"type": "\"default\" | \"line\"",
|
|
93
|
+
"default": "\"default\""
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "orientation",
|
|
97
|
+
"type": "\"horizontal\" | \"vertical\"",
|
|
98
|
+
"default": "\"horizontal\""
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"example": "<Tabs defaultValue=\"tab1\">\n <TabsList>\n <TabsTrigger value=\"tab1\">Aba 1</TabsTrigger>\n <TabsTrigger value=\"tab2\">Aba 2</TabsTrigger>\n </TabsList>\n <TabsContent value=\"tab1\">Conteudo 1</TabsContent>\n <TabsContent value=\"tab2\">Conteudo 2</TabsContent>\n</Tabs>",
|
|
102
|
+
"keywords": [
|
|
103
|
+
"tabs",
|
|
104
|
+
"abas",
|
|
105
|
+
"navegacao",
|
|
106
|
+
"tab",
|
|
107
|
+
"painel"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "VideoPlayer",
|
|
112
|
+
"import": "import { VideoPlayer } from \"@fluencypassdevs/cycle\"\nimport type { VideoPlayerRef, CaptionTrack } from \"@fluencypassdevs/cycle\"",
|
|
113
|
+
"description": "Player de video (Vidstack). Suporta MP4, WebM, HLS. Src aceita URL string ou { src, type } (VideoPlayerSrc) para blob: de arquivo local e URL sem extensao — para blob, passar type do File.type (normalizado internamente). Chapters, captions/subtitles (multiplos idiomas via CaptionTrack[]), buffering spinner, live indicator, tooltips. Expoe ref imperativo (play/pause), callbacks onTimeUpdate/onEnded e labels para i18n de todos os textos dos controles. Cue de legenda desktop estilizado pelo DS (caixa escura arredondada, 15px). Menus mobile curados para contexto de aula: sem audio gain, sem Google Cast (AirPlay mantido), sem toggles de demo — em Acessibilidade sobra Estilos de legenda (e o menu some inteiro quando o video nao tem legenda), com corpo minimo legivel de 14px.",
|
|
114
|
+
"props": [
|
|
115
|
+
{
|
|
116
|
+
"name": "src",
|
|
117
|
+
"type": "string | { src: string; type: string }",
|
|
118
|
+
"default": "-"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "title",
|
|
122
|
+
"type": "string",
|
|
123
|
+
"default": "-"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "chapters",
|
|
127
|
+
"type": "string (VTT URL)",
|
|
128
|
+
"default": "-"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "captions",
|
|
132
|
+
"type": "CaptionTrack[]",
|
|
133
|
+
"default": "-"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "showBuffering",
|
|
137
|
+
"type": "boolean",
|
|
138
|
+
"default": "true"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"name": "startTime",
|
|
142
|
+
"type": "number",
|
|
143
|
+
"default": "-"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "locale",
|
|
147
|
+
"type": "PlayerLocale",
|
|
148
|
+
"default": "\"pt-BR\""
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "labels",
|
|
152
|
+
"type": "Partial<VideoDesktopLabels>",
|
|
153
|
+
"default": "-"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "onTimeUpdate",
|
|
157
|
+
"type": "(currentTime: number, duration: number) => void",
|
|
158
|
+
"default": "-"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"name": "onEnded",
|
|
162
|
+
"type": "() => void",
|
|
163
|
+
"default": "-"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "ref",
|
|
167
|
+
"type": "React.Ref<VideoPlayerRef>",
|
|
168
|
+
"default": "-"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"example": "<VideoPlayer src=\"/video.mp4\" title=\"Aula 1\" />\n\n{/* Com legendas em multiplos idiomas */}\n<VideoPlayer\n src=\"/video.mp4\"\n title=\"Aula 1\"\n captions={[\n { src: \"/subs/pt.vtt\", language: \"pt-BR\", label: \"Portugues\", default: true },\n { src: \"/subs/en.vtt\", language: \"en\", label: \"English\" },\n ]}\n/>\n\n// Ref imperativo + callbacks:\nconst ref = useRef<VideoPlayerRef>(null)\n<VideoPlayer\n ref={ref}\n src=\"/video.mp4\"\n onTimeUpdate={(currentTime, duration) => reportProgress(currentTime / duration)}\n onEnded={() => markAsCompleted()}\n/>\n// ref.current.play() / ref.current.pause()",
|
|
172
|
+
"keywords": [
|
|
173
|
+
"video",
|
|
174
|
+
"player",
|
|
175
|
+
"aula",
|
|
176
|
+
"assistir",
|
|
177
|
+
"mp4",
|
|
178
|
+
"stream",
|
|
179
|
+
"hls",
|
|
180
|
+
"live",
|
|
181
|
+
"legenda",
|
|
182
|
+
"caption",
|
|
183
|
+
"subtitle"
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"name": "Accordion",
|
|
188
|
+
"import": "import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from \"@fluencypassdevs/cycle\"",
|
|
189
|
+
"description": "Secoes colapsaveis com animacao. Suporta single e multiple.",
|
|
190
|
+
"props": [
|
|
191
|
+
{
|
|
192
|
+
"name": "type",
|
|
193
|
+
"type": "\"single\" | \"multiple\"",
|
|
194
|
+
"default": "\"single\""
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"name": "collapsible",
|
|
198
|
+
"type": "boolean",
|
|
199
|
+
"default": "false"
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
"example": "<Accordion type=\"single\" collapsible>\n <AccordionItem value=\"item-1\">\n <AccordionTrigger>Secao 1</AccordionTrigger>\n <AccordionContent>Conteudo aqui</AccordionContent>\n </AccordionItem>\n</Accordion>",
|
|
203
|
+
"keywords": [
|
|
204
|
+
"accordion",
|
|
205
|
+
"colapsavel",
|
|
206
|
+
"expandir",
|
|
207
|
+
"secao",
|
|
208
|
+
"faq",
|
|
209
|
+
"pergunta"
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "Progress",
|
|
214
|
+
"import": "import { Progress } from \"@fluencypassdevs/cycle\"",
|
|
215
|
+
"description": "Barra de progresso. 4 sizes (xs, sm, default, lg), 4 variants (default, secondary, destructive, muted). Prop theme aplica cor apenas no indicator.",
|
|
216
|
+
"props": [
|
|
217
|
+
{
|
|
218
|
+
"name": "value",
|
|
219
|
+
"type": "number",
|
|
220
|
+
"default": "0"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"name": "size",
|
|
224
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\"",
|
|
225
|
+
"default": "\"default\""
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"name": "variant",
|
|
229
|
+
"type": "\"default\" | \"secondary\" | \"destructive\" | \"muted\"",
|
|
230
|
+
"default": "\"default\""
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"name": "theme",
|
|
234
|
+
"type": "string",
|
|
235
|
+
"default": "-"
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
"example": "<Progress value={60} />\n<Progress value={80} size=\"lg\" theme=\"brand\" />",
|
|
239
|
+
"keywords": [
|
|
240
|
+
"progress",
|
|
241
|
+
"progresso",
|
|
242
|
+
"barra",
|
|
243
|
+
"loading",
|
|
244
|
+
"porcentagem",
|
|
245
|
+
"completar"
|
|
246
|
+
]
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "Badge",
|
|
250
|
+
"import": "import { Badge } from \"@fluencypassdevs/cycle\"",
|
|
251
|
+
"description": "Badge com 10 variants (default, secondary, destructive, outline, ghost, link, muted, success, progress, progress-completed), 3 sizes (sm, default, lg). Suporte a temas via .theme-*.",
|
|
252
|
+
"props": [
|
|
253
|
+
{
|
|
254
|
+
"name": "variant",
|
|
255
|
+
"type": "\"default\" | \"secondary\" | \"destructive\" | \"outline\" | \"ghost\" | \"link\" | \"muted\" | \"success\" | \"progress\" | \"progress-completed\"",
|
|
256
|
+
"default": "\"default\""
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"name": "size",
|
|
260
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
261
|
+
"default": "\"default\""
|
|
262
|
+
}
|
|
263
|
+
],
|
|
264
|
+
"example": "<Badge>Novo</Badge>\n<Badge variant=\"success\" size=\"sm\">Completo</Badge>\n<Badge variant=\"progress\">Em progresso</Badge>",
|
|
265
|
+
"keywords": [
|
|
266
|
+
"badge",
|
|
267
|
+
"tag",
|
|
268
|
+
"etiqueta",
|
|
269
|
+
"status",
|
|
270
|
+
"label",
|
|
271
|
+
"chip"
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"name": "ScrollArea",
|
|
276
|
+
"import": "import { ScrollArea, ScrollBar } from \"@fluencypassdevs/cycle\"",
|
|
277
|
+
"description": "Area de scroll customizada com scrollbar estilizado. Vertical e horizontal.",
|
|
278
|
+
"props": [],
|
|
279
|
+
"example": "<ScrollArea className=\"h-72 w-48\">\n <div>Conteudo longo...</div>\n</ScrollArea>",
|
|
280
|
+
"keywords": [
|
|
281
|
+
"scroll",
|
|
282
|
+
"scrollbar",
|
|
283
|
+
"rolagem",
|
|
284
|
+
"area"
|
|
285
|
+
]
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"name": "ProgressStage",
|
|
289
|
+
"import": "import { ProgressStage } from \"@fluencypassdevs/cycle\"",
|
|
290
|
+
"description": "Progresso segmentado em pills (2-10 stages). Prop theme aplica cor apenas nas pills preenchidas.",
|
|
291
|
+
"props": [
|
|
292
|
+
{
|
|
293
|
+
"name": "current",
|
|
294
|
+
"type": "number",
|
|
295
|
+
"default": "0"
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name": "total",
|
|
299
|
+
"type": "number (2-10)",
|
|
300
|
+
"default": "5"
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"name": "theme",
|
|
304
|
+
"type": "string",
|
|
305
|
+
"default": "-"
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"example": "<ProgressStage current={3} total={5} />\n<ProgressStage current={2} total={4} theme=\"brand\" />",
|
|
309
|
+
"keywords": [
|
|
310
|
+
"progress",
|
|
311
|
+
"stage",
|
|
312
|
+
"etapa",
|
|
313
|
+
"passo",
|
|
314
|
+
"step",
|
|
315
|
+
"wizard",
|
|
316
|
+
"segmentado"
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"name": "ProgressDot",
|
|
321
|
+
"import": "import { ProgressDot } from \"@fluencypassdevs/cycle\"",
|
|
322
|
+
"description": "Progresso em dots circulares (2-10 stages). 4 sizes (xs=4px, sm=6px, default=8px, lg=12px). Prop theme aplica cor nos dots preenchidos.",
|
|
323
|
+
"props": [
|
|
324
|
+
{
|
|
325
|
+
"name": "current",
|
|
326
|
+
"type": "number",
|
|
327
|
+
"default": "0"
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"name": "total",
|
|
331
|
+
"type": "number (2-10)",
|
|
332
|
+
"default": "5"
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "size",
|
|
336
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\"",
|
|
337
|
+
"default": "\"default\""
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"name": "theme",
|
|
341
|
+
"type": "string",
|
|
342
|
+
"default": "-"
|
|
343
|
+
}
|
|
344
|
+
],
|
|
345
|
+
"example": "<ProgressDot current={2} total={5} />\n<ProgressDot current={1} total={3} size=\"lg\" theme=\"brand\" />",
|
|
346
|
+
"keywords": [
|
|
347
|
+
"progress",
|
|
348
|
+
"dot",
|
|
349
|
+
"ponto",
|
|
350
|
+
"indicador",
|
|
351
|
+
"carousel",
|
|
352
|
+
"slide",
|
|
353
|
+
"paginacao"
|
|
354
|
+
]
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"name": "CircularProgress",
|
|
358
|
+
"import": "import { CircularProgress } from \"@fluencypassdevs/cycle\"",
|
|
359
|
+
"description": "Indicador de progresso circular com porcentagem 0-100 no centro. 4 sizes (xs=48px, sm=64px, default=80px, lg=120px). Prop autoTheme escolhe cor baseada no value (0-33 critical, 34-66 warning, 67-100 positive). Prop theme aceita qualquer dos 8 temas Cycle.",
|
|
360
|
+
"props": [
|
|
361
|
+
{
|
|
362
|
+
"name": "value",
|
|
363
|
+
"type": "number (0-100)",
|
|
364
|
+
"default": "-"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"name": "size",
|
|
368
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\"",
|
|
369
|
+
"default": "\"default\""
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"name": "theme",
|
|
373
|
+
"type": "string",
|
|
374
|
+
"default": "-"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"name": "autoTheme",
|
|
378
|
+
"type": "boolean",
|
|
379
|
+
"default": "false"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"name": "showLabel",
|
|
383
|
+
"type": "boolean",
|
|
384
|
+
"default": "true"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "label",
|
|
388
|
+
"type": "string",
|
|
389
|
+
"default": "-"
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
"example": "<CircularProgress value={70} />\n<CircularProgress value={25} autoTheme />\n<CircularProgress value={80} theme=\"theme-class\" size=\"lg\" />\n<CircularProgress value={50} showLabel={false} />",
|
|
393
|
+
"keywords": [
|
|
394
|
+
"progress",
|
|
395
|
+
"circular",
|
|
396
|
+
"circle",
|
|
397
|
+
"anel",
|
|
398
|
+
"ring",
|
|
399
|
+
"porcentagem",
|
|
400
|
+
"percentage",
|
|
401
|
+
"score",
|
|
402
|
+
"nota",
|
|
403
|
+
"aproveitamento"
|
|
404
|
+
]
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"name": "Container",
|
|
408
|
+
"import": "import { Container } from \"@fluencypassdevs/cycle\"",
|
|
409
|
+
"description": "Layout primitive: wrapper centralizado com max-width e margin LOCKED do design system (16/24px). Use sempre como wrapper de paginas/secoes. Margin custom (ex: 40px desktop) via className override.",
|
|
410
|
+
"props": [
|
|
411
|
+
{
|
|
412
|
+
"name": "size",
|
|
413
|
+
"type": "\"prose\" | \"default\" | \"wide\" | \"full\"",
|
|
414
|
+
"default": "\"default\""
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"name": "padding",
|
|
418
|
+
"type": "\"default\" | \"none\"",
|
|
419
|
+
"default": "\"default\""
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"name": "as",
|
|
423
|
+
"type": "\"div\" | \"section\" | \"main\" | \"article\"",
|
|
424
|
+
"default": "\"div\""
|
|
425
|
+
}
|
|
426
|
+
],
|
|
427
|
+
"example": "<Container>conteudo principal (max 1380px, margin 16/24)</Container>\n<Container size=\"prose\">leitura/forms (max 860px)</Container>\n<Container padding=\"none\">hero full-bleed</Container>\n\n{/* Override custom (raro) */}\n<Container className=\"sm:px-10\">conteudo com mais respiro (40px desktop)</Container>",
|
|
428
|
+
"keywords": [
|
|
429
|
+
"container",
|
|
430
|
+
"wrapper",
|
|
431
|
+
"max-width",
|
|
432
|
+
"centralizar",
|
|
433
|
+
"layout",
|
|
434
|
+
"secao",
|
|
435
|
+
"pagina",
|
|
436
|
+
"margin"
|
|
437
|
+
]
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
"name": "Stack",
|
|
441
|
+
"import": "import { Stack } from \"@fluencypassdevs/cycle\"",
|
|
442
|
+
"description": "Layout primitive: flex com gap, direction e alinhamento. Use em vez de flex flex-col gap-X manual. Gap tokens xs=4 sm=8 md=12 lg=16 xl=24 px.",
|
|
443
|
+
"props": [
|
|
444
|
+
{
|
|
445
|
+
"name": "direction",
|
|
446
|
+
"type": "\"col\" | \"row\"",
|
|
447
|
+
"default": "\"col\""
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
"name": "directionSm",
|
|
451
|
+
"type": "\"col\" | \"row\"",
|
|
452
|
+
"default": "-"
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"name": "directionLg",
|
|
456
|
+
"type": "\"col\" | \"row\"",
|
|
457
|
+
"default": "-"
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"name": "gap",
|
|
461
|
+
"type": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"",
|
|
462
|
+
"default": "\"lg\""
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"name": "gapSm",
|
|
466
|
+
"type": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"",
|
|
467
|
+
"default": "-"
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"name": "align",
|
|
471
|
+
"type": "\"start\" | \"center\" | \"end\" | \"stretch\"",
|
|
472
|
+
"default": "-"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"name": "justify",
|
|
476
|
+
"type": "\"start\" | \"center\" | \"end\" | \"between\"",
|
|
477
|
+
"default": "-"
|
|
478
|
+
}
|
|
479
|
+
],
|
|
480
|
+
"example": "<Stack gap=\"xl\">vertical</Stack>\n<Stack direction=\"col\" directionSm=\"row\" justify=\"between\">action bar responsivo</Stack>\n<Stack gap=\"md\" gapSm=\"xl\">gap responsivo</Stack>",
|
|
481
|
+
"keywords": [
|
|
482
|
+
"stack",
|
|
483
|
+
"flex",
|
|
484
|
+
"vstack",
|
|
485
|
+
"hstack",
|
|
486
|
+
"vertical",
|
|
487
|
+
"horizontal",
|
|
488
|
+
"gap",
|
|
489
|
+
"espacamento"
|
|
490
|
+
]
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"name": "Grid",
|
|
494
|
+
"import": "import { Grid, GridItem } from \"@fluencypassdevs/cycle\"",
|
|
495
|
+
"description": "Layout primitive: CSS grid totalmente prescrito. 12 colunas FIXAS, gutter LOCKED (16px mobile, 24px desktop). Items usam GridItem com size 1-12 para ocupar fracoes. Sem props pra cols/gap — sistema decide tudo. Apenas minItemWidth para galerias auto-fit.",
|
|
496
|
+
"props": [
|
|
497
|
+
{
|
|
498
|
+
"name": "minItemWidth",
|
|
499
|
+
"type": "string",
|
|
500
|
+
"default": "-"
|
|
501
|
+
}
|
|
502
|
+
],
|
|
503
|
+
"example": "{/* 3 cards iguais (1 mobile, 3 desktop) */}\n<Grid>\n <GridItem size={12} sizeMd={4}>Card</GridItem>\n <GridItem size={12} sizeMd={4}>Card</GridItem>\n <GridItem size={12} sizeMd={4}>Card</GridItem>\n</Grid>\n\n{/* Hero + 2 metades */}\n<Grid>\n <GridItem size={12}>Hero</GridItem>\n <GridItem size={12} sizeMd={6}>Card A</GridItem>\n <GridItem size={12} sizeMd={6}>Card B</GridItem>\n</Grid>\n\n{/* Galeria auto-fit */}\n<Grid minItemWidth=\"280px\">cards</Grid>",
|
|
504
|
+
"keywords": [
|
|
505
|
+
"grid",
|
|
506
|
+
"colunas",
|
|
507
|
+
"cols",
|
|
508
|
+
"responsive",
|
|
509
|
+
"layout",
|
|
510
|
+
"cards",
|
|
511
|
+
"12-col"
|
|
512
|
+
]
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"name": "GridItem",
|
|
516
|
+
"import": "import { GridItem } from \"@fluencypassdevs/cycle\"",
|
|
517
|
+
"description": "Filho do Grid. Define quantas das 12 colunas ocupar em cada breakpoint via size/sizeSm/sizeMd/sizeLg. Pense em fracoes: size=12 (full), size=6 (1/2), size=4 (1/3), size=3 (1/4).",
|
|
518
|
+
"props": [
|
|
519
|
+
{
|
|
520
|
+
"name": "size",
|
|
521
|
+
"type": "1 a 12",
|
|
522
|
+
"default": "-"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
"name": "sizeSm",
|
|
526
|
+
"type": "1 a 12",
|
|
527
|
+
"default": "-"
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
"name": "sizeMd",
|
|
531
|
+
"type": "1 a 12",
|
|
532
|
+
"default": "-"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
"name": "sizeLg",
|
|
536
|
+
"type": "1 a 12",
|
|
537
|
+
"default": "-"
|
|
538
|
+
}
|
|
539
|
+
],
|
|
540
|
+
"example": "{/* Full no mobile, metade no desktop */}\n<GridItem size={12} sizeMd={6}>Card</GridItem>\n\n{/* Sempre um terco */}\n<GridItem size={4}>1/3</GridItem>\n\n{/* Sidebar 1/4 desktop */}\n<GridItem size={12} sizeMd={3}>Sidebar</GridItem>",
|
|
541
|
+
"keywords": [
|
|
542
|
+
"grid",
|
|
543
|
+
"item",
|
|
544
|
+
"size",
|
|
545
|
+
"col-span",
|
|
546
|
+
"colunas",
|
|
547
|
+
"child",
|
|
548
|
+
"fracao"
|
|
549
|
+
]
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
"name": "Checkbox",
|
|
553
|
+
"import": "import { Checkbox } from \"@fluencypassdevs/cycle\"",
|
|
554
|
+
"description": "Checkbox com 3 sizes (sm, default, lg), 2 variants (default, circular). Prop theme aplica cor no estado checked.",
|
|
555
|
+
"props": [
|
|
556
|
+
{
|
|
557
|
+
"name": "size",
|
|
558
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
559
|
+
"default": "\"default\""
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"name": "variant",
|
|
563
|
+
"type": "\"default\" | \"circular\"",
|
|
564
|
+
"default": "\"default\""
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
"name": "theme",
|
|
568
|
+
"type": "string",
|
|
569
|
+
"default": "-"
|
|
570
|
+
}
|
|
571
|
+
],
|
|
572
|
+
"example": "<Checkbox />\n<Checkbox size=\"lg\" variant=\"circular\" />",
|
|
573
|
+
"keywords": [
|
|
574
|
+
"checkbox",
|
|
575
|
+
"check",
|
|
576
|
+
"marcar",
|
|
577
|
+
"selecionar",
|
|
578
|
+
"formulario",
|
|
579
|
+
"toggle"
|
|
580
|
+
]
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
"name": "RadioGroup",
|
|
584
|
+
"import": "import { RadioGroup, RadioGroupItem } from \"@fluencypassdevs/cycle\"",
|
|
585
|
+
"description": "Radio button com 3 sizes (sm, default, lg). Prop theme aplica cor no estado checked.",
|
|
586
|
+
"props": [
|
|
587
|
+
{
|
|
588
|
+
"name": "size",
|
|
589
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
590
|
+
"default": "\"default\""
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
"name": "theme",
|
|
594
|
+
"type": "string",
|
|
595
|
+
"default": "-"
|
|
596
|
+
}
|
|
597
|
+
],
|
|
598
|
+
"example": "<RadioGroup defaultValue=\"a\">\n <RadioGroupItem value=\"a\" id=\"a\" />\n <Label htmlFor=\"a\">Opcao A</Label>\n <RadioGroupItem value=\"b\" id=\"b\" />\n <Label htmlFor=\"b\">Opcao B</Label>\n</RadioGroup>",
|
|
599
|
+
"keywords": [
|
|
600
|
+
"radio",
|
|
601
|
+
"opcao",
|
|
602
|
+
"selecionar",
|
|
603
|
+
"formulario",
|
|
604
|
+
"escolher"
|
|
605
|
+
]
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
"name": "FileCard",
|
|
609
|
+
"import": "import { FileCard } from \"@fluencypassdevs/cycle\"",
|
|
610
|
+
"description": "Botao de download com icone, titulo, tipo e tamanho. 3 sizes (sm, md, lg).",
|
|
611
|
+
"props": [
|
|
612
|
+
{
|
|
613
|
+
"name": "title",
|
|
614
|
+
"type": "string",
|
|
615
|
+
"default": "-"
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
"name": "fileType",
|
|
619
|
+
"type": "string",
|
|
620
|
+
"default": "-"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"name": "fileSize",
|
|
624
|
+
"type": "string",
|
|
625
|
+
"default": "-"
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"name": "size",
|
|
629
|
+
"type": "\"sm\" | \"md\" | \"lg\"",
|
|
630
|
+
"default": "\"md\""
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
"name": "icon",
|
|
634
|
+
"type": "LucideIcon",
|
|
635
|
+
"default": "FileDown"
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
"name": "onClick",
|
|
639
|
+
"type": "() => void",
|
|
640
|
+
"default": "-"
|
|
641
|
+
}
|
|
642
|
+
],
|
|
643
|
+
"example": "<FileCard title=\"Material da aula\" fileType=\"PDF\" fileSize=\"2.4 MB\" onClick={() => download()} />",
|
|
644
|
+
"keywords": [
|
|
645
|
+
"file",
|
|
646
|
+
"arquivo",
|
|
647
|
+
"download",
|
|
648
|
+
"card",
|
|
649
|
+
"pdf",
|
|
650
|
+
"documento",
|
|
651
|
+
"anexo"
|
|
652
|
+
]
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
"name": "CycleIcon",
|
|
656
|
+
"import": "import { CycleIcon } from \"@fluencypassdevs/cycle\"\nimport { Home, Search, Settings } from \"@fluencypassdevs/cycle/icons/lucide\"",
|
|
657
|
+
"description": "Wrapper para icones Lucide com size/stroke tokens. OBRIGATORIO: icones Lucide SEMPRE de @fluencypassdevs/cycle/icons/lucide, NUNCA de lucide-react.",
|
|
658
|
+
"props": [
|
|
659
|
+
{
|
|
660
|
+
"name": "icon",
|
|
661
|
+
"type": "LucideIcon",
|
|
662
|
+
"default": "-"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"name": "size",
|
|
666
|
+
"type": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"",
|
|
667
|
+
"default": "\"sm\""
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
"name": "decorative",
|
|
671
|
+
"type": "boolean",
|
|
672
|
+
"default": "false"
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
"name": "aria-label",
|
|
676
|
+
"type": "string",
|
|
677
|
+
"default": "-"
|
|
678
|
+
}
|
|
679
|
+
],
|
|
680
|
+
"example": "import { CycleIcon } from \"@fluencypassdevs/cycle\"\nimport { Home, Search } from \"@fluencypassdevs/cycle/icons/lucide\"\n\n<CycleIcon icon={Home} size=\"sm\" decorative />\n<CycleIcon icon={Search} size=\"md\" aria-label=\"Buscar\" />",
|
|
681
|
+
"keywords": [
|
|
682
|
+
"icone",
|
|
683
|
+
"icon",
|
|
684
|
+
"lucide",
|
|
685
|
+
"svg",
|
|
686
|
+
"grafico"
|
|
687
|
+
]
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"name": "Switch",
|
|
691
|
+
"import": "import { Switch } from \"@fluencypassdevs/cycle\"",
|
|
692
|
+
"description": "Toggle on/off. 3 sizes (sm, default, lg). Prop theme aplica cor no estado checked.",
|
|
693
|
+
"props": [
|
|
694
|
+
{
|
|
695
|
+
"name": "size",
|
|
696
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
697
|
+
"default": "\"default\""
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
"name": "theme",
|
|
701
|
+
"type": "string",
|
|
702
|
+
"default": "-"
|
|
703
|
+
}
|
|
704
|
+
],
|
|
705
|
+
"example": "<Switch />\n<Switch size=\"lg\" />",
|
|
706
|
+
"keywords": [
|
|
707
|
+
"switch",
|
|
708
|
+
"toggle",
|
|
709
|
+
"ligar",
|
|
710
|
+
"desligar",
|
|
711
|
+
"on",
|
|
712
|
+
"off"
|
|
713
|
+
]
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"name": "Slider",
|
|
717
|
+
"import": "import { Slider } from \"@fluencypassdevs/cycle\"",
|
|
718
|
+
"description": "Controle deslizante com 3 sizes (sm, default, lg), suporte a range (2 thumbs). Suporta .theme-*.",
|
|
719
|
+
"props": [
|
|
720
|
+
{
|
|
721
|
+
"name": "size",
|
|
722
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
723
|
+
"default": "\"default\""
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
"name": "defaultValue",
|
|
727
|
+
"type": "number[]",
|
|
728
|
+
"default": "[50]"
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
"name": "min",
|
|
732
|
+
"type": "number",
|
|
733
|
+
"default": "0"
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
"name": "max",
|
|
737
|
+
"type": "number",
|
|
738
|
+
"default": "100"
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
"name": "step",
|
|
742
|
+
"type": "number",
|
|
743
|
+
"default": "1"
|
|
744
|
+
}
|
|
745
|
+
],
|
|
746
|
+
"example": "<Slider defaultValue={[50]} max={100} step={1} />\n<Slider defaultValue={[25, 75]} /> {/* range */}",
|
|
747
|
+
"keywords": [
|
|
748
|
+
"slider",
|
|
749
|
+
"deslizante",
|
|
750
|
+
"range",
|
|
751
|
+
"volume",
|
|
752
|
+
"controle"
|
|
753
|
+
]
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
"name": "AudioPlayer",
|
|
757
|
+
"import": "import { AudioPlayer } from \"@fluencypassdevs/cycle\"\nimport type { AudioPlayerRef } from \"@fluencypassdevs/cycle\"",
|
|
758
|
+
"description": "Player de audio (Vidstack). 2 variantes (default, card). Suporta MP3, WAV, M4A, HLS. Src aceita URL string ou { src, type } (AudioPlayerSrc) para blob: de arquivo local e URL sem extensao — para blob, passar type do File.type (normalizado internamente). showSpeed=true por padrao. Expoe ref imperativo (play/pause), callbacks onTimeUpdate/onEnded e labels para i18n.",
|
|
759
|
+
"props": [
|
|
760
|
+
{
|
|
761
|
+
"name": "src",
|
|
762
|
+
"type": "string | { src: string; type: string }",
|
|
763
|
+
"default": "-"
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
"name": "variant",
|
|
767
|
+
"type": "\"default\" | \"card\"",
|
|
768
|
+
"default": "\"default\""
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"name": "title",
|
|
772
|
+
"type": "string",
|
|
773
|
+
"default": "-"
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
"name": "description",
|
|
777
|
+
"type": "string",
|
|
778
|
+
"default": "-"
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
"name": "showSpeed",
|
|
782
|
+
"type": "boolean",
|
|
783
|
+
"default": "true"
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
"name": "startTime",
|
|
787
|
+
"type": "number",
|
|
788
|
+
"default": "-"
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
"name": "locale",
|
|
792
|
+
"type": "PlayerLocale",
|
|
793
|
+
"default": "\"pt-BR\""
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
"name": "labels",
|
|
797
|
+
"type": "AudioPlayerLabels",
|
|
798
|
+
"default": "-"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
"name": "onTimeUpdate",
|
|
802
|
+
"type": "(currentTime: number, duration: number) => void",
|
|
803
|
+
"default": "-"
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
"name": "onEnded",
|
|
807
|
+
"type": "() => void",
|
|
808
|
+
"default": "-"
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
"name": "ref",
|
|
812
|
+
"type": "React.Ref<AudioPlayerRef>",
|
|
813
|
+
"default": "-"
|
|
814
|
+
}
|
|
815
|
+
],
|
|
816
|
+
"example": "<AudioPlayer src=\"/audio.mp3\" />\n<AudioPlayer variant=\"card\" src=\"/audio.mp3\" title=\"Listening Practice\" description=\"Episode 1\" />\n\n// Ref imperativo + callbacks:\nconst ref = useRef<AudioPlayerRef>(null)\n<AudioPlayer\n ref={ref}\n src=\"/audio.mp3\"\n title=\"Lesson 1\"\n onTimeUpdate={(currentTime, duration) => console.log(currentTime, duration)}\n onEnded={() => console.log(\"ended\")}\n/>\n// ref.current.play() / ref.current.pause()",
|
|
817
|
+
"keywords": [
|
|
818
|
+
"audio",
|
|
819
|
+
"player",
|
|
820
|
+
"musica",
|
|
821
|
+
"podcast",
|
|
822
|
+
"som",
|
|
823
|
+
"mp3",
|
|
824
|
+
"ouvir",
|
|
825
|
+
"listening"
|
|
826
|
+
]
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
"name": "LiveWaiting",
|
|
830
|
+
"import": "import { LiveWaiting } from \"@fluencypassdevs/cycle\"",
|
|
831
|
+
"description": "Tela de espera para lives com countdown em tempo real, badge, info do professor (Avatar) e topico.",
|
|
832
|
+
"props": [
|
|
833
|
+
{
|
|
834
|
+
"name": "scheduledAt",
|
|
835
|
+
"type": "Date",
|
|
836
|
+
"default": "-"
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
"name": "teacherName",
|
|
840
|
+
"type": "string",
|
|
841
|
+
"default": "-"
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
"name": "teacherAvatar",
|
|
845
|
+
"type": "string",
|
|
846
|
+
"default": "-"
|
|
847
|
+
},
|
|
848
|
+
{
|
|
849
|
+
"name": "topic",
|
|
850
|
+
"type": "string",
|
|
851
|
+
"default": "-"
|
|
852
|
+
}
|
|
853
|
+
],
|
|
854
|
+
"example": "<LiveWaiting scheduledAt={new Date(\"2026-03-25T19:00\")} teacherName=\"Prof. Ana\" topic=\"Speaking Practice\" />",
|
|
855
|
+
"keywords": [
|
|
856
|
+
"live",
|
|
857
|
+
"espera",
|
|
858
|
+
"waiting",
|
|
859
|
+
"countdown",
|
|
860
|
+
"aula",
|
|
861
|
+
"evento",
|
|
862
|
+
"timer"
|
|
863
|
+
]
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
"name": "Avatar",
|
|
867
|
+
"import": "import { Avatar, AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup } from \"@fluencypassdevs/cycle\"",
|
|
868
|
+
"description": "Avatar com imagem, fallback de iniciais, badge de status e group. 3 sizes (sm=24px, default=32px, lg=40px).",
|
|
869
|
+
"props": [
|
|
870
|
+
{
|
|
871
|
+
"name": "size",
|
|
872
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
873
|
+
"default": "\"default\""
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
"name": "theme",
|
|
877
|
+
"type": "string",
|
|
878
|
+
"default": "-"
|
|
879
|
+
}
|
|
880
|
+
],
|
|
881
|
+
"example": "<Avatar size=\"lg\">\n <AvatarImage src=\"/foto.jpg\" alt=\"Nome\" />\n <AvatarFallback>FP</AvatarFallback>\n <AvatarBadge status=\"online\" />\n</Avatar>\n\n<AvatarGroup>\n <Avatar><AvatarFallback>A</AvatarFallback></Avatar>\n <Avatar><AvatarFallback>B</AvatarFallback></Avatar>\n</AvatarGroup>",
|
|
882
|
+
"keywords": [
|
|
883
|
+
"avatar",
|
|
884
|
+
"foto",
|
|
885
|
+
"imagem",
|
|
886
|
+
"usuario",
|
|
887
|
+
"perfil",
|
|
888
|
+
"iniciais",
|
|
889
|
+
"group"
|
|
890
|
+
]
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
"name": "ChatBubble",
|
|
894
|
+
"import": "import { ChatBubble } from \"@fluencypassdevs/cycle\"",
|
|
895
|
+
"description": "Bolha de mensagem. 3 variantes: default (aluno), instructor (professor com destaque primary), system (mensagem central italico).",
|
|
896
|
+
"props": [
|
|
897
|
+
{
|
|
898
|
+
"name": "variant",
|
|
899
|
+
"type": "\"default\" | \"instructor\" | \"system\"",
|
|
900
|
+
"default": "\"default\""
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
"name": "message",
|
|
904
|
+
"type": "string",
|
|
905
|
+
"default": "-"
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
"name": "sender",
|
|
909
|
+
"type": "string",
|
|
910
|
+
"default": "-"
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
"name": "avatarSrc",
|
|
914
|
+
"type": "string",
|
|
915
|
+
"default": "-"
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
"name": "timestamp",
|
|
919
|
+
"type": "string",
|
|
920
|
+
"default": "-"
|
|
921
|
+
}
|
|
922
|
+
],
|
|
923
|
+
"example": "<ChatBubble variant=\"default\" sender=\"Aluno\" message=\"Oi, professor!\" timestamp=\"14:30\" />\n<ChatBubble variant=\"instructor\" sender=\"Professor\" message=\"Oi! Vamos comecar.\" />",
|
|
924
|
+
"keywords": [
|
|
925
|
+
"chat",
|
|
926
|
+
"mensagem",
|
|
927
|
+
"bolha",
|
|
928
|
+
"conversa",
|
|
929
|
+
"bubble",
|
|
930
|
+
"message"
|
|
931
|
+
]
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
"name": "ChatPanel",
|
|
935
|
+
"import": "import { ChatPanel } from \"@fluencypassdevs/cycle\"",
|
|
936
|
+
"description": "Painel de chat completo com lista de ChatBubbles, scroll automatico, e campo de input para envio.",
|
|
937
|
+
"props": [
|
|
938
|
+
{
|
|
939
|
+
"name": "messages",
|
|
940
|
+
"type": "ChatMessage[]",
|
|
941
|
+
"default": "[]"
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
"name": "onSend",
|
|
945
|
+
"type": "(msg: string) => void",
|
|
946
|
+
"default": "-"
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
"name": "currentUser",
|
|
950
|
+
"type": "string",
|
|
951
|
+
"default": "-"
|
|
952
|
+
}
|
|
953
|
+
],
|
|
954
|
+
"example": "<ChatPanel messages={messages} onSend={handleSend} currentUser=\"aluno@email.com\" />",
|
|
955
|
+
"keywords": [
|
|
956
|
+
"chat",
|
|
957
|
+
"painel",
|
|
958
|
+
"conversa",
|
|
959
|
+
"mensagens",
|
|
960
|
+
"live",
|
|
961
|
+
"tempo real"
|
|
962
|
+
]
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
"name": "ChatMessage",
|
|
966
|
+
"import": "import { ChatMessage } from \"@fluencypassdevs/cycle\"",
|
|
967
|
+
"description": "Mensagem de conversa com IA. Persona ai/user/system, suporta texto + audio inline + like/dislike. Loading state com typing indicator. AI usa icone Ai + bubble transparente. User usa bubble pink coral (theme-brand) + avatar. CONVENCAO DO PRODUTO: (1) toda msg da IA com `audioSrc` deve ter `text` (roteiro/legenda do TTS); (2) toda msg do user com `audioSrc` deve ter `text` (transcricao gerada por IA). Garante acessibilidade (leitura + escuta), busca no historico e suporte a screen readers.",
|
|
968
|
+
"props": [
|
|
969
|
+
{
|
|
970
|
+
"name": "persona",
|
|
971
|
+
"type": "\"ai\" | \"user\" | \"system\"",
|
|
972
|
+
"default": "-"
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
"name": "text",
|
|
976
|
+
"type": "string",
|
|
977
|
+
"default": "-",
|
|
978
|
+
"note": "Em ai com audioSrc, e o roteiro do TTS. Em user com audioSrc, e a transcricao."
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
"name": "audioSrc",
|
|
982
|
+
"type": "string",
|
|
983
|
+
"default": "-",
|
|
984
|
+
"note": "IA: TTS gerado. User: gravacao do microfone. Em ambos, sempre acompanhe com text."
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
"name": "avatar",
|
|
988
|
+
"type": "string",
|
|
989
|
+
"default": "-"
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
"name": "author",
|
|
993
|
+
"type": "string",
|
|
994
|
+
"default": "-"
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
"name": "showFeedback",
|
|
998
|
+
"type": "boolean",
|
|
999
|
+
"default": "false"
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
"name": "feedbackValue",
|
|
1003
|
+
"type": "\"like\" | \"dislike\" | null",
|
|
1004
|
+
"default": "-"
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
"name": "onFeedbackChange",
|
|
1008
|
+
"type": "(val) => void",
|
|
1009
|
+
"default": "-"
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
"name": "loading",
|
|
1013
|
+
"type": "boolean",
|
|
1014
|
+
"default": "false"
|
|
1015
|
+
}
|
|
1016
|
+
],
|
|
1017
|
+
"example": "{/* IA: sempre com text + audioSrc (convencao) */}\n<ChatMessage persona=\"ai\" text=\"Como posso ajudar?\" audioSrc=\"/ai-tts.mp3\" showFeedback />\n{/* User com audio: SEMPRE inclua text com a transcricao */}\n<ChatMessage persona=\"user\" text=\"Can you explain present perfect?\" audioSrc=\"/user-rec.mp3\" author=\"Felipe\" />\n{/* User so com texto (digitado): audio nao se aplica */}\n<ChatMessage persona=\"user\" text=\"Oi\" avatar=\"/me.jpg\" author=\"Felipe\" />\n<ChatMessage persona=\"ai\" loading />\n<ChatMessage persona=\"system\" text=\"Conversa iniciada\" />",
|
|
1018
|
+
"keywords": [
|
|
1019
|
+
"chat",
|
|
1020
|
+
"ai",
|
|
1021
|
+
"ia",
|
|
1022
|
+
"mensagem",
|
|
1023
|
+
"conversa",
|
|
1024
|
+
"message",
|
|
1025
|
+
"assistant",
|
|
1026
|
+
"bot"
|
|
1027
|
+
]
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
"name": "MessageRating",
|
|
1031
|
+
"import": "import { MessageRating } from \"@fluencypassdevs/cycle\"",
|
|
1032
|
+
"description": "Rating de 5 niveis com emoji usado ao final de uma conversa. Niveis: Disappointing/Frustrating/Ok/Helpful/Loved it. Layout horizontal (desktop) ou vertical (mobile). Labels customizaveis para i18n.",
|
|
1033
|
+
"props": [
|
|
1034
|
+
{
|
|
1035
|
+
"name": "value",
|
|
1036
|
+
"type": "1 | 2 | 3 | 4 | 5 | null",
|
|
1037
|
+
"default": "-"
|
|
1038
|
+
},
|
|
1039
|
+
{
|
|
1040
|
+
"name": "defaultValue",
|
|
1041
|
+
"type": "1 | 2 | 3 | 4 | 5 | null",
|
|
1042
|
+
"default": "-"
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
"name": "onChange",
|
|
1046
|
+
"type": "(val) => void",
|
|
1047
|
+
"default": "-"
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
"name": "layout",
|
|
1051
|
+
"type": "\"horizontal\" | \"vertical\" | \"auto\"",
|
|
1052
|
+
"default": "\"auto\""
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
"name": "labels",
|
|
1056
|
+
"type": "Partial<MessageRatingLabels>",
|
|
1057
|
+
"default": "-"
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
"name": "disabled",
|
|
1061
|
+
"type": "boolean",
|
|
1062
|
+
"default": "false"
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
"name": "title",
|
|
1066
|
+
"type": "string",
|
|
1067
|
+
"default": "-"
|
|
1068
|
+
}
|
|
1069
|
+
],
|
|
1070
|
+
"example": "<MessageRating onChange={(v) => save(v)} title=\"Como foi sua experiencia?\" />\n<MessageRating value={3} disabled />",
|
|
1071
|
+
"keywords": [
|
|
1072
|
+
"rating",
|
|
1073
|
+
"emoji",
|
|
1074
|
+
"avaliacao",
|
|
1075
|
+
"feedback",
|
|
1076
|
+
"experiencia",
|
|
1077
|
+
"score",
|
|
1078
|
+
"satisfacao"
|
|
1079
|
+
]
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
"name": "MessageBar",
|
|
1083
|
+
"import": "import { MessageBar } from \"@fluencypassdevs/cycle\"",
|
|
1084
|
+
"description": "Input bar para chat com IA. 6 estados: default, audio-only, active, disabled, recording, paused. UI-only: consumer implementa MediaRecorder + HTMLAudioElement via callbacks. Live waveform real durante recording (Web Audio API, rolling window estilo WhatsApp). RecordedWaveform real durante paused com peaks + barras tocadas/nao-tocadas + dot verde + click/drag-to-seek. Press-to-record no mobile (touch-only): long-press inicia, drag-up trava em hands-free, drag-left cancela, release < 1s cancela, release >= 1s envia. Vibracao haptica em lock/cancel. Suporta limite de duracao via maxRecordingDuration (segundos) com warning visual configuravel nos segundos finais (timer destructive + 'Xs restantes' aria-live) e callback onMaxDurationReached ao atingir o limite.",
|
|
1085
|
+
"props": [
|
|
1086
|
+
{
|
|
1087
|
+
"name": "state",
|
|
1088
|
+
"type": "\"default\" | \"audio-only\" | \"active\" | \"disabled\" | \"recording\" | \"paused\"",
|
|
1089
|
+
"default": "\"default\""
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
"name": "value",
|
|
1093
|
+
"type": "string",
|
|
1094
|
+
"default": "\"\""
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
"name": "onChange",
|
|
1098
|
+
"type": "(val) => void",
|
|
1099
|
+
"default": "-"
|
|
1100
|
+
},
|
|
1101
|
+
{
|
|
1102
|
+
"name": "onSendText",
|
|
1103
|
+
"type": "(text) => void",
|
|
1104
|
+
"default": "-"
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
"name": "onStartRecording",
|
|
1108
|
+
"type": "() => void",
|
|
1109
|
+
"default": "-"
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
"name": "onPauseRecording",
|
|
1113
|
+
"type": "() => void",
|
|
1114
|
+
"default": "-"
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
"name": "onResumeRecording",
|
|
1118
|
+
"type": "() => void",
|
|
1119
|
+
"default": "-"
|
|
1120
|
+
},
|
|
1121
|
+
{
|
|
1122
|
+
"name": "onCancelRecording",
|
|
1123
|
+
"type": "() => void",
|
|
1124
|
+
"default": "-"
|
|
1125
|
+
},
|
|
1126
|
+
{
|
|
1127
|
+
"name": "onSendAudio",
|
|
1128
|
+
"type": "() => void",
|
|
1129
|
+
"default": "-"
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
"name": "onTogglePlay",
|
|
1133
|
+
"type": "() => void",
|
|
1134
|
+
"default": "-"
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
"name": "recordingDuration",
|
|
1138
|
+
"type": "number",
|
|
1139
|
+
"default": "0"
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
"name": "isPlaying",
|
|
1143
|
+
"type": "boolean",
|
|
1144
|
+
"default": "false"
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
"name": "recordingStream",
|
|
1148
|
+
"type": "MediaStream | null",
|
|
1149
|
+
"default": "null",
|
|
1150
|
+
"note": "passe o MESMO stream do MediaRecorder; o componente analisa em tempo real para renderizar o live waveform"
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
"name": "playbackProgress",
|
|
1154
|
+
"type": "number (0-1)",
|
|
1155
|
+
"default": "0",
|
|
1156
|
+
"note": "consumer atualiza via audio.ontimeupdate enquanto toca o preview no estado paused"
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
"name": "onSeekPlayback",
|
|
1160
|
+
"type": "(progress) => void",
|
|
1161
|
+
"default": "-",
|
|
1162
|
+
"note": "consumer seta audio.currentTime = progress * duration"
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
"name": "placeholder",
|
|
1166
|
+
"type": "string",
|
|
1167
|
+
"default": "\"Digite sua mensagem...\""
|
|
1168
|
+
},
|
|
1169
|
+
{
|
|
1170
|
+
"name": "maxRecordingDuration",
|
|
1171
|
+
"type": "number",
|
|
1172
|
+
"default": "-",
|
|
1173
|
+
"note": "limite em segundos. Quando atingido, dispara onMaxDurationReached uma vez. Sem isso, sem limite."
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
"name": "warnAtSecondsLeft",
|
|
1177
|
+
"type": "number",
|
|
1178
|
+
"default": "10",
|
|
1179
|
+
"note": "ativa warning visual nos ultimos N segundos (timer destructive + 'Xs restantes' aria-live polite)"
|
|
1180
|
+
},
|
|
1181
|
+
{
|
|
1182
|
+
"name": "onMaxDurationReached",
|
|
1183
|
+
"type": "() => void",
|
|
1184
|
+
"default": "-",
|
|
1185
|
+
"note": "disparado uma vez ao atingir o limite. ChatThread usa pra auto-pausar; consumer puro pode usar pra customizar"
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
"name": "secondsLeftLabel",
|
|
1189
|
+
"type": "(s) => string",
|
|
1190
|
+
"default": "(s) => `${s}s restantes`",
|
|
1191
|
+
"note": "label do warning (pra i18n)"
|
|
1192
|
+
}
|
|
1193
|
+
],
|
|
1194
|
+
"example": "// 1) Captura: passa o MESMO stream pro MessageBar (live waveform).\n// 2) Pause: recorder.stop() gera o Blob; crie um <audio> e atualize playbackProgress via ontimeupdate.\n// 3) Cleanup: revokeObjectURL ao cancelar/enviar.\n\n<MessageBar value={text} onChange={setText} onSendText={(t) => send(t)} onStartRecording={() => startRec()} />\n<MessageBar state=\"recording\" recordingDuration={4} recordingStream={stream} onPauseRecording={pause} onCancelRecording={cancel} onSendAudio={send} />\n<MessageBar state=\"paused\" recordingDuration={42} isPlaying={isPlaying} playbackProgress={progress} onTogglePlay={togglePlay} onSeekPlayback={seek} onResumeRecording={resume} onCancelRecording={cancel} onSendAudio={send} />\n{/* Com limite de duracao (timer fica vermelho aos ultimos 5s, auto-pausa aos 30s) */}\n<MessageBar state=\"recording\" recordingDuration={duration} recordingStream={stream} maxRecordingDuration={30} warnAtSecondsLeft={5} onMaxDurationReached={() => pause()} onPauseRecording={pause} onSendAudio={send} />",
|
|
1195
|
+
"keywords": [
|
|
1196
|
+
"chat",
|
|
1197
|
+
"input",
|
|
1198
|
+
"message",
|
|
1199
|
+
"bar",
|
|
1200
|
+
"audio",
|
|
1201
|
+
"recording",
|
|
1202
|
+
"microphone",
|
|
1203
|
+
"mensagem",
|
|
1204
|
+
"envio",
|
|
1205
|
+
"press-to-record",
|
|
1206
|
+
"waveform",
|
|
1207
|
+
"playback",
|
|
1208
|
+
"whatsapp"
|
|
1209
|
+
]
|
|
1210
|
+
},
|
|
1211
|
+
{
|
|
1212
|
+
"name": "ChatThread",
|
|
1213
|
+
"import": "import { ChatThread, type ChatThreadMessage } from \"@fluencypassdevs/cycle\"",
|
|
1214
|
+
"description": "Composite 'tela de chat pronta' que junta ChatMessage + MessageBar + MessageRating. Gerencia state machine interno do MessageBar (default↔recording↔paused) baseado nos callbacks. Auto-scroll inteligente (preserva posicao se user subiu + botao '↓ nova mensagem'). Scroll infinito via onLoadMore. Banners configuraveis: offline, rateLimitedUntil (countdown), quotaExhausted (AlertDialog). Retry inline em msgs failed do user (B2) e regenerar resposta da IA (B3). Botao 'Parar resposta' durante thinking e OPT-IN via presenca de onStopResponse — sem callback, MessageBar some com animacao de saida e volta quando IA termina. requestRating per-message renderiza MessageRating inline embaixo da bubble da IA — escolha some imediato, callback onRate(messageId, value, label) permite consumer enviar como msg do user. initialThinking pra conversas que comecam com IA falando. Input controlled internamente. Animacoes fade+slide (200ms enter / 150ms leave). Suporta limite de duracao de gravacao via maxRecordingDuration (segundos) com warning visual configuravel e auto-pause ao atingir; override via onMaxDurationReached.",
|
|
1215
|
+
"props": [
|
|
1216
|
+
{
|
|
1217
|
+
"name": "messages",
|
|
1218
|
+
"type": "ChatThreadMessage[]",
|
|
1219
|
+
"default": "[]",
|
|
1220
|
+
"note": "array de mensagens da conversa"
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
"name": "state",
|
|
1224
|
+
"type": "\"idle\" | \"sending\" | \"thinking\" | \"error\"",
|
|
1225
|
+
"default": "\"idle\"",
|
|
1226
|
+
"note": "estado global da conversa (controlled)"
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
"name": "initialThinking",
|
|
1230
|
+
"type": "boolean",
|
|
1231
|
+
"default": "false",
|
|
1232
|
+
"note": "quando true e thread vazio, monta direto em thinking (cenario IA fala primeiro)"
|
|
1233
|
+
},
|
|
1234
|
+
{
|
|
1235
|
+
"name": "audioOnlyMode",
|
|
1236
|
+
"type": "boolean",
|
|
1237
|
+
"default": "false",
|
|
1238
|
+
"note": "MessageBar interno em modo apenas audio (sem input texto)"
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
"name": "onSendText",
|
|
1242
|
+
"type": "(text) => void",
|
|
1243
|
+
"default": "-"
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
"name": "onSendAudio",
|
|
1247
|
+
"type": "() => void",
|
|
1248
|
+
"default": "-",
|
|
1249
|
+
"note": "dispara quando user confirma envio (consumer pega Blob do MediaRecorder proprio)"
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
"name": "onStartRecording",
|
|
1253
|
+
"type": "() => void",
|
|
1254
|
+
"default": "-",
|
|
1255
|
+
"note": "consumer chama getUserMedia + cria MediaRecorder"
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
"name": "onPauseRecording",
|
|
1259
|
+
"type": "() => void",
|
|
1260
|
+
"default": "-",
|
|
1261
|
+
"note": "consumer faz recorder.stop() + cria Blob para preview"
|
|
1262
|
+
},
|
|
1263
|
+
{
|
|
1264
|
+
"name": "onResumeRecording",
|
|
1265
|
+
"type": "() => void",
|
|
1266
|
+
"default": "-"
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
"name": "onCancelRecording",
|
|
1270
|
+
"type": "() => void",
|
|
1271
|
+
"default": "-"
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
"name": "onTogglePlay",
|
|
1275
|
+
"type": "() => void",
|
|
1276
|
+
"default": "-"
|
|
1277
|
+
},
|
|
1278
|
+
{
|
|
1279
|
+
"name": "onSeekPlayback",
|
|
1280
|
+
"type": "(progress) => void",
|
|
1281
|
+
"default": "-"
|
|
1282
|
+
},
|
|
1283
|
+
{
|
|
1284
|
+
"name": "recordingStream",
|
|
1285
|
+
"type": "MediaStream | null",
|
|
1286
|
+
"default": "null",
|
|
1287
|
+
"note": "pra live waveform durante recording"
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
"name": "recordingDuration",
|
|
1291
|
+
"type": "number",
|
|
1292
|
+
"default": "0"
|
|
1293
|
+
},
|
|
1294
|
+
{
|
|
1295
|
+
"name": "isPlaying",
|
|
1296
|
+
"type": "boolean",
|
|
1297
|
+
"default": "false"
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
"name": "playbackProgress",
|
|
1301
|
+
"type": "number (0-1)",
|
|
1302
|
+
"default": "0"
|
|
1303
|
+
},
|
|
1304
|
+
{
|
|
1305
|
+
"name": "onRetryMessage",
|
|
1306
|
+
"type": "(messageId) => void",
|
|
1307
|
+
"default": "-",
|
|
1308
|
+
"note": "retry msg do user com status=failed"
|
|
1309
|
+
},
|
|
1310
|
+
{
|
|
1311
|
+
"name": "onRegenerateResponse",
|
|
1312
|
+
"type": "() => void",
|
|
1313
|
+
"default": "-",
|
|
1314
|
+
"note": "regerar resposta da IA com erro"
|
|
1315
|
+
},
|
|
1316
|
+
{
|
|
1317
|
+
"name": "onStopResponse",
|
|
1318
|
+
"type": "() => void",
|
|
1319
|
+
"default": "-",
|
|
1320
|
+
"note": "OPT-IN: passar este callback ativa o botao 'Parar resposta' durante thinking. Sem ele, MessageBar some com animacao e volta quando IA termina."
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
"name": "onLoadMore",
|
|
1324
|
+
"type": "() => Promise<void>",
|
|
1325
|
+
"default": "-",
|
|
1326
|
+
"note": "scroll infinito ao chegar no topo (G1)"
|
|
1327
|
+
},
|
|
1328
|
+
{
|
|
1329
|
+
"name": "offline",
|
|
1330
|
+
"type": "boolean",
|
|
1331
|
+
"default": "false",
|
|
1332
|
+
"note": "banner topo + MessageBar disabled"
|
|
1333
|
+
},
|
|
1334
|
+
{
|
|
1335
|
+
"name": "rateLimitedUntil",
|
|
1336
|
+
"type": "number | null",
|
|
1337
|
+
"default": "null",
|
|
1338
|
+
"note": "timestamp epoch ate quando bloquear (banner countdown)"
|
|
1339
|
+
},
|
|
1340
|
+
{
|
|
1341
|
+
"name": "quotaExhausted",
|
|
1342
|
+
"type": "boolean",
|
|
1343
|
+
"default": "false",
|
|
1344
|
+
"note": "abre AlertDialog modal"
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
"name": "quotaExhaustedConfig",
|
|
1348
|
+
"type": "{ title, description, ctaLabel, onCta }",
|
|
1349
|
+
"default": "-",
|
|
1350
|
+
"note": "conteudo do modal configuravel"
|
|
1351
|
+
},
|
|
1352
|
+
{
|
|
1353
|
+
"name": "onRate",
|
|
1354
|
+
"type": "(messageId, value, label) => void",
|
|
1355
|
+
"default": "-",
|
|
1356
|
+
"note": "rating de uma msg da IA com requestRating=true"
|
|
1357
|
+
},
|
|
1358
|
+
{
|
|
1359
|
+
"name": "ratingLabels",
|
|
1360
|
+
"type": "Partial<MessageRatingLabels>",
|
|
1361
|
+
"default": "PT-BR defaults",
|
|
1362
|
+
"note": "labels customizadas do rating"
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
"name": "placeholder",
|
|
1366
|
+
"type": "string",
|
|
1367
|
+
"default": "\"Digite sua mensagem...\""
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
"name": "maxLength",
|
|
1371
|
+
"type": "number",
|
|
1372
|
+
"default": "-"
|
|
1373
|
+
},
|
|
1374
|
+
{
|
|
1375
|
+
"name": "userAvatar",
|
|
1376
|
+
"type": "string",
|
|
1377
|
+
"default": "-",
|
|
1378
|
+
"note": "URL do avatar do user — propagado pra todas as msgs do user automaticamente"
|
|
1379
|
+
},
|
|
1380
|
+
{
|
|
1381
|
+
"name": "userName",
|
|
1382
|
+
"type": "string",
|
|
1383
|
+
"default": "-",
|
|
1384
|
+
"note": "Nome do user — usado para iniciais no fallback do avatar e alt da imagem"
|
|
1385
|
+
},
|
|
1386
|
+
{
|
|
1387
|
+
"name": "maxRecordingDuration",
|
|
1388
|
+
"type": "number",
|
|
1389
|
+
"default": "-",
|
|
1390
|
+
"note": "limite de duracao da gravacao em segundos. Ao atingir, auto-pausa (vai pro preview) a menos que onMaxDurationReached seja passado"
|
|
1391
|
+
},
|
|
1392
|
+
{
|
|
1393
|
+
"name": "warnAtSecondsLeft",
|
|
1394
|
+
"type": "number",
|
|
1395
|
+
"default": "10",
|
|
1396
|
+
"note": "passthrough pro MessageBar — quando ativar o warning visual nos segundos finais"
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
"name": "onMaxDurationReached",
|
|
1400
|
+
"type": "() => void",
|
|
1401
|
+
"default": "-",
|
|
1402
|
+
"note": "OVERRIDE do auto-pause. Quando passado, consumer assume controle ao atingir o limite"
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
"name": "secondsLeftLabel",
|
|
1406
|
+
"type": "(s) => string",
|
|
1407
|
+
"default": "(s) => `${s}s restantes`",
|
|
1408
|
+
"note": "passthrough pro MessageBar (pra i18n)"
|
|
1409
|
+
}
|
|
1410
|
+
],
|
|
1411
|
+
"example": "// ChatThreadMessage extra fields:\n// - status?: \"sent\" | \"pending\" | \"failed\"\n// - text?: string\n// - audioSrc?: string (URL ou Blob URL)\n// - audioPeaks?: number[]\n// - errorText?: string (msg de erro custom para AI failed)\n// - requestRating?: boolean (true na msg da IA que pede avaliacao — renderiza MessageRating inline)\n\n<ChatThread\n messages={messages}\n state={state}\n initialThinking\n userAvatar=\"/me.jpg\"\n userName=\"Felipe Pereira\"\n onSendText={(text) => sendText(text)}\n onSendAudio={() => sendAudio()}\n onStartRecording={() => startRec()}\n onPauseRecording={() => pauseRec()}\n onRate={(msgId, value, label) => {\n setMessages((m) => [...m, { id: newId(), persona: \"user\", status: \"sent\", text: label.subtitle }])\n }}\n/>",
|
|
1412
|
+
"keywords": [
|
|
1413
|
+
"chat",
|
|
1414
|
+
"thread",
|
|
1415
|
+
"conversation",
|
|
1416
|
+
"conversa",
|
|
1417
|
+
"ai",
|
|
1418
|
+
"ia",
|
|
1419
|
+
"composite",
|
|
1420
|
+
"tela",
|
|
1421
|
+
"screen",
|
|
1422
|
+
"rating",
|
|
1423
|
+
"scroll",
|
|
1424
|
+
"thinking",
|
|
1425
|
+
"offline",
|
|
1426
|
+
"rate-limit",
|
|
1427
|
+
"quota",
|
|
1428
|
+
"feedback"
|
|
1429
|
+
]
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
"name": "SelectorBar",
|
|
1433
|
+
"import": "import { SelectorBar } from \"@fluencypassdevs/cycle\"",
|
|
1434
|
+
"description": "Barra seletora de contexto (mobile-first): overline (rotulo pequeno) + titulo + slot badge a direita + affordance de seletor (ChevronsUpDown via CycleIcon). Trigger tipico de um Drawer (bottom sheet) com a lista de opcoes — compoe com <DrawerTrigger asChild> (forwardRef). aria-haspopup=dialog + aria-expanded via prop open. Nao usar para disclosure inline (Collapsible) nem navegacao hierarquica (Breadcrumb). Origem: barra de unidades do Class mobile.",
|
|
1435
|
+
"props": [
|
|
1436
|
+
{
|
|
1437
|
+
"name": "title",
|
|
1438
|
+
"type": "string",
|
|
1439
|
+
"default": "-",
|
|
1440
|
+
"note": "obrigatoria — titulo principal (ex: unidade atual)"
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
"name": "overline",
|
|
1444
|
+
"type": "string",
|
|
1445
|
+
"default": "-",
|
|
1446
|
+
"note": "rotulo pequeno acima do titulo (ex: nome do curso)"
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
"name": "badge",
|
|
1450
|
+
"type": "React.ReactNode",
|
|
1451
|
+
"default": "-",
|
|
1452
|
+
"note": "slot a direita, antes do icone (ex: <Badge variant='progress'>0/7</Badge>)"
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
"name": "open",
|
|
1456
|
+
"type": "boolean",
|
|
1457
|
+
"default": "-",
|
|
1458
|
+
"note": "estado da superficie controlada (reflete em aria-expanded)"
|
|
1459
|
+
}
|
|
1460
|
+
],
|
|
1461
|
+
"example": "<Drawer open={open} onOpenChange={setOpen}>\n <DrawerTrigger asChild>\n <SelectorBar\n overline=\"Beginner 1\"\n title=\"Family and Jobs\"\n badge={<Badge variant=\"progress\" size=\"sm\">0/7</Badge>}\n open={open}\n />\n </DrawerTrigger>\n <DrawerContent>{/* lista de opcoes */}</DrawerContent>\n</Drawer>",
|
|
1462
|
+
"keywords": [
|
|
1463
|
+
"selector",
|
|
1464
|
+
"bar",
|
|
1465
|
+
"seletor",
|
|
1466
|
+
"contexto",
|
|
1467
|
+
"unidade",
|
|
1468
|
+
"curso",
|
|
1469
|
+
"bottom sheet",
|
|
1470
|
+
"drawer",
|
|
1471
|
+
"trigger",
|
|
1472
|
+
"mobile",
|
|
1473
|
+
"trocar"
|
|
1474
|
+
]
|
|
1475
|
+
},
|
|
1476
|
+
{
|
|
1477
|
+
"name": "Toggle",
|
|
1478
|
+
"import": "import { Toggle } from \"@fluencypassdevs/cycle\"",
|
|
1479
|
+
"description": "Botao toggle (on/off). 2 variants (default, outline), 8 sizes. Prop fillOnPress para preencher icones SVG no estado on.",
|
|
1480
|
+
"props": [
|
|
1481
|
+
{
|
|
1482
|
+
"name": "variant",
|
|
1483
|
+
"type": "\"default\" | \"outline\"",
|
|
1484
|
+
"default": "\"default\""
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
"name": "size",
|
|
1488
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\" | \"icon-xs\" | \"icon-sm\" | \"icon-default\" | \"icon-lg\"",
|
|
1489
|
+
"default": "\"default\""
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
"name": "fillOnPress",
|
|
1493
|
+
"type": "boolean",
|
|
1494
|
+
"default": "false"
|
|
1495
|
+
}
|
|
1496
|
+
],
|
|
1497
|
+
"example": "<Toggle><CycleIcon icon={Bold} size=\"sm\" decorative /> Bold</Toggle>\n<Toggle size=\"icon-sm\" fillOnPress><CycleIcon icon={Heart} size=\"sm\" decorative /></Toggle>",
|
|
1498
|
+
"keywords": [
|
|
1499
|
+
"toggle",
|
|
1500
|
+
"botao",
|
|
1501
|
+
"pressionar",
|
|
1502
|
+
"favorito",
|
|
1503
|
+
"bold",
|
|
1504
|
+
"italico"
|
|
1505
|
+
]
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
"name": "Label",
|
|
1509
|
+
"import": "import { Label } from \"@fluencypassdevs/cycle\"",
|
|
1510
|
+
"description": "Rotulo acessivel para campos de formulario. Baseado no Radix UI Label.",
|
|
1511
|
+
"props": [
|
|
1512
|
+
{
|
|
1513
|
+
"name": "htmlFor",
|
|
1514
|
+
"type": "string",
|
|
1515
|
+
"default": "-"
|
|
1516
|
+
}
|
|
1517
|
+
],
|
|
1518
|
+
"example": "<Label htmlFor=\"email\">Email</Label>\n<Input id=\"email\" />",
|
|
1519
|
+
"keywords": [
|
|
1520
|
+
"label",
|
|
1521
|
+
"rotulo",
|
|
1522
|
+
"formulario",
|
|
1523
|
+
"campo",
|
|
1524
|
+
"acessibilidade"
|
|
1525
|
+
]
|
|
1526
|
+
},
|
|
1527
|
+
{
|
|
1528
|
+
"name": "Textarea",
|
|
1529
|
+
"import": "import { Textarea } from \"@fluencypassdevs/cycle\"",
|
|
1530
|
+
"description": "Campo multi-linha. 2 variantes (outline, filled), 3 sizes (sm=60px, default=80px, lg=120px). Mesmos tokens do Input. Resize-y.",
|
|
1531
|
+
"props": [
|
|
1532
|
+
{
|
|
1533
|
+
"name": "variant",
|
|
1534
|
+
"type": "\"outline\" | \"filled\"",
|
|
1535
|
+
"default": "\"outline\""
|
|
1536
|
+
},
|
|
1537
|
+
{
|
|
1538
|
+
"name": "textareaSize",
|
|
1539
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
1540
|
+
"default": "\"default\""
|
|
1541
|
+
}
|
|
1542
|
+
],
|
|
1543
|
+
"example": "<Textarea placeholder=\"Escreva aqui...\" />\n<Textarea variant=\"filled\" textareaSize=\"lg\" />",
|
|
1544
|
+
"keywords": [
|
|
1545
|
+
"textarea",
|
|
1546
|
+
"texto",
|
|
1547
|
+
"multi-linha",
|
|
1548
|
+
"comentario",
|
|
1549
|
+
"mensagem",
|
|
1550
|
+
"descricao"
|
|
1551
|
+
]
|
|
1552
|
+
},
|
|
1553
|
+
{
|
|
1554
|
+
"name": "LikeDislike",
|
|
1555
|
+
"import": "import { LikeDislike } from \"@fluencypassdevs/cycle\"",
|
|
1556
|
+
"description": "Botoes de like/dislike mutuamente exclusivos. 4 sizes (xs, sm, default, lg). Animacao burst no like. Feedback opcional no dislike via Textarea.",
|
|
1557
|
+
"props": [
|
|
1558
|
+
{
|
|
1559
|
+
"name": "size",
|
|
1560
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\"",
|
|
1561
|
+
"default": "\"default\""
|
|
1562
|
+
},
|
|
1563
|
+
{
|
|
1564
|
+
"name": "value",
|
|
1565
|
+
"type": "\"like\" | \"dislike\" | null",
|
|
1566
|
+
"default": "null"
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
"name": "onValueChange",
|
|
1570
|
+
"type": "(val) => void",
|
|
1571
|
+
"default": "-"
|
|
1572
|
+
},
|
|
1573
|
+
{
|
|
1574
|
+
"name": "showFeedback",
|
|
1575
|
+
"type": "boolean",
|
|
1576
|
+
"default": "false"
|
|
1577
|
+
}
|
|
1578
|
+
],
|
|
1579
|
+
"example": "<LikeDislike onValueChange={(val) => console.log(val)} />\n<LikeDislike showFeedback onFeedbackSubmit={(text) => save(text)} />",
|
|
1580
|
+
"keywords": [
|
|
1581
|
+
"like",
|
|
1582
|
+
"dislike",
|
|
1583
|
+
"feedback",
|
|
1584
|
+
"avaliacao",
|
|
1585
|
+
"curtir",
|
|
1586
|
+
"positivo",
|
|
1587
|
+
"negativo"
|
|
1588
|
+
]
|
|
1589
|
+
},
|
|
1590
|
+
{
|
|
1591
|
+
"name": "Sonner (Toast)",
|
|
1592
|
+
"import": "import { Toaster, cycleToast } from \"@fluencypassdevs/cycle\"",
|
|
1593
|
+
"description": "Notificacoes temporarias (toast). cycleToast.positive/critical/warning/info aplica temas Cycle. Requer <Toaster /> no layout.",
|
|
1594
|
+
"props": [],
|
|
1595
|
+
"example": "// No layout raiz:\n<Toaster />\n\n// Para disparar:\ncycleToast.positive(\"Salvo com sucesso!\")\ncycleToast.critical(\"Erro ao salvar\")\ncycleToast.warning(\"Atencao: limite proximo\")\ncycleToast.info(\"Nova mensagem recebida\")",
|
|
1596
|
+
"keywords": [
|
|
1597
|
+
"toast",
|
|
1598
|
+
"notificacao",
|
|
1599
|
+
"snackbar",
|
|
1600
|
+
"alerta",
|
|
1601
|
+
"mensagem",
|
|
1602
|
+
"sonner",
|
|
1603
|
+
"feedback"
|
|
1604
|
+
]
|
|
1605
|
+
},
|
|
1606
|
+
{
|
|
1607
|
+
"name": "Alert",
|
|
1608
|
+
"import": "import { Alert, AlertTitle, AlertDescription, AlertAction, AlertClose } from \"@fluencypassdevs/cycle\"",
|
|
1609
|
+
"description": "Alerta informativo com icone, acao e close. 6 variantes: default, destructive, positive, warning, critical, info.",
|
|
1610
|
+
"props": [
|
|
1611
|
+
{
|
|
1612
|
+
"name": "variant",
|
|
1613
|
+
"type": "\"default\" | \"destructive\" | \"positive\" | \"warning\" | \"critical\" | \"info\"",
|
|
1614
|
+
"default": "\"default\""
|
|
1615
|
+
}
|
|
1616
|
+
],
|
|
1617
|
+
"example": "<Alert variant=\"positive\">\n <AlertTitle>Sucesso</AlertTitle>\n <AlertDescription>Dados salvos com sucesso.</AlertDescription>\n <AlertAction onClick={() => undo()}>Desfazer</AlertAction>\n <AlertClose />\n</Alert>",
|
|
1618
|
+
"keywords": [
|
|
1619
|
+
"alert",
|
|
1620
|
+
"alerta",
|
|
1621
|
+
"aviso",
|
|
1622
|
+
"notificacao",
|
|
1623
|
+
"info",
|
|
1624
|
+
"warning",
|
|
1625
|
+
"erro",
|
|
1626
|
+
"sucesso"
|
|
1627
|
+
]
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
"name": "AlertDialog",
|
|
1631
|
+
"import": "import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogAction, AlertDialogCancel } from \"@fluencypassdevs/cycle\"",
|
|
1632
|
+
"description": "Dialog de confirmacao modal. 2 sizes (default, sm). Media/icone, titulo, descricao, botoes de acao e cancelar.",
|
|
1633
|
+
"props": [
|
|
1634
|
+
{
|
|
1635
|
+
"name": "size",
|
|
1636
|
+
"type": "\"default\" | \"sm\"",
|
|
1637
|
+
"default": "\"default\""
|
|
1638
|
+
}
|
|
1639
|
+
],
|
|
1640
|
+
"example": "<AlertDialog>\n <AlertDialogTrigger asChild><Button variant=\"destructive\">Excluir</Button></AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Tem certeza?</AlertDialogTitle>\n <AlertDialogDescription>Esta acao nao pode ser desfeita.</AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancelar</AlertDialogCancel>\n <AlertDialogAction>Confirmar</AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n</AlertDialog>",
|
|
1641
|
+
"keywords": [
|
|
1642
|
+
"dialog",
|
|
1643
|
+
"confirmacao",
|
|
1644
|
+
"modal",
|
|
1645
|
+
"excluir",
|
|
1646
|
+
"deletar",
|
|
1647
|
+
"confirmar",
|
|
1648
|
+
"alert"
|
|
1649
|
+
]
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
"name": "Select",
|
|
1653
|
+
"import": "import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel, SelectSeparator } from \"@fluencypassdevs/cycle\"",
|
|
1654
|
+
"description": "Dropdown de selecao. 2 sizes (sm, default). Suporta grupos, labels, separadores e scroll.",
|
|
1655
|
+
"props": [
|
|
1656
|
+
{
|
|
1657
|
+
"name": "size",
|
|
1658
|
+
"type": "\"sm\" | \"default\"",
|
|
1659
|
+
"default": "\"default\""
|
|
1660
|
+
}
|
|
1661
|
+
],
|
|
1662
|
+
"example": "<Select>\n <SelectTrigger><SelectValue placeholder=\"Selecione...\" /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"a\">Opcao A</SelectItem>\n <SelectItem value=\"b\">Opcao B</SelectItem>\n </SelectContent>\n</Select>",
|
|
1663
|
+
"keywords": [
|
|
1664
|
+
"select",
|
|
1665
|
+
"dropdown",
|
|
1666
|
+
"selecao",
|
|
1667
|
+
"opcao",
|
|
1668
|
+
"escolher",
|
|
1669
|
+
"lista",
|
|
1670
|
+
"combo"
|
|
1671
|
+
]
|
|
1672
|
+
},
|
|
1673
|
+
{
|
|
1674
|
+
"name": "DropdownMenu",
|
|
1675
|
+
"import": "import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem } from \"@fluencypassdevs/cycle\"",
|
|
1676
|
+
"description": "Menu contextual com acoes, submenus, checkbox items, radio items, separadores e shortcuts. Baseado no Radix DropdownMenu. Variant destructive para itens perigosos.",
|
|
1677
|
+
"props": [
|
|
1678
|
+
{
|
|
1679
|
+
"name": "variant (MenuItem)",
|
|
1680
|
+
"type": "\"default\" | \"destructive\"",
|
|
1681
|
+
"default": "\"default\""
|
|
1682
|
+
},
|
|
1683
|
+
{
|
|
1684
|
+
"name": "inset (MenuItem/Label)",
|
|
1685
|
+
"type": "boolean",
|
|
1686
|
+
"default": "false"
|
|
1687
|
+
}
|
|
1688
|
+
],
|
|
1689
|
+
"example": "<DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\">Abrir menu</Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"w-56\">\n <DropdownMenuLabel>Minha conta</DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <CycleIcon icon={User} size=\"sm\" decorative /> Perfil\n <DropdownMenuShortcut>Ctrl+P</DropdownMenuShortcut>\n </DropdownMenuItem>\n <DropdownMenuItem>\n <CycleIcon icon={Settings} size=\"sm\" decorative /> Config\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\">\n <CycleIcon icon={LogOut} size=\"sm\" decorative /> Sair\n </DropdownMenuItem>\n </DropdownMenuContent>\n</DropdownMenu>",
|
|
1690
|
+
"keywords": [
|
|
1691
|
+
"dropdown",
|
|
1692
|
+
"menu",
|
|
1693
|
+
"contextual",
|
|
1694
|
+
"acoes",
|
|
1695
|
+
"actions",
|
|
1696
|
+
"submenu",
|
|
1697
|
+
"context-menu"
|
|
1698
|
+
]
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
"name": "Popover",
|
|
1702
|
+
"import": "import { Popover, PopoverTrigger, PopoverContent } from \"@fluencypassdevs/cycle\"",
|
|
1703
|
+
"description": "Conteudo flutuante ancorado a um trigger. Header, titulo e descricao.",
|
|
1704
|
+
"props": [],
|
|
1705
|
+
"example": "<Popover>\n <PopoverTrigger asChild><Button variant=\"outline\">Info</Button></PopoverTrigger>\n <PopoverContent>Conteudo do popover</PopoverContent>\n</Popover>",
|
|
1706
|
+
"keywords": [
|
|
1707
|
+
"popover",
|
|
1708
|
+
"flutuante",
|
|
1709
|
+
"tooltip",
|
|
1710
|
+
"info",
|
|
1711
|
+
"detalhes",
|
|
1712
|
+
"popup"
|
|
1713
|
+
]
|
|
1714
|
+
},
|
|
1715
|
+
{
|
|
1716
|
+
"name": "Tooltip",
|
|
1717
|
+
"import": "import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from \"@fluencypassdevs/cycle\"",
|
|
1718
|
+
"description": "Dica de texto ao hover/focus. Requer TooltipProvider no layout raiz.",
|
|
1719
|
+
"props": [],
|
|
1720
|
+
"example": "// No layout raiz:\n<TooltipProvider>...</TooltipProvider>\n\n// Uso:\n<Tooltip>\n <TooltipTrigger asChild><Button variant=\"ghost\">?</Button></TooltipTrigger>\n <TooltipContent>Texto de ajuda</TooltipContent>\n</Tooltip>",
|
|
1721
|
+
"keywords": [
|
|
1722
|
+
"tooltip",
|
|
1723
|
+
"dica",
|
|
1724
|
+
"ajuda",
|
|
1725
|
+
"hover",
|
|
1726
|
+
"hint",
|
|
1727
|
+
"info"
|
|
1728
|
+
]
|
|
1729
|
+
},
|
|
1730
|
+
{
|
|
1731
|
+
"name": "Resizable",
|
|
1732
|
+
"import": "import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from \"@fluencypassdevs/cycle\"",
|
|
1733
|
+
"description": "Paineis redimensionaveis com handle de arraste. Horizontal e vertical.",
|
|
1734
|
+
"props": [
|
|
1735
|
+
{
|
|
1736
|
+
"name": "direction",
|
|
1737
|
+
"type": "\"horizontal\" | \"vertical\"",
|
|
1738
|
+
"default": "\"horizontal\""
|
|
1739
|
+
}
|
|
1740
|
+
],
|
|
1741
|
+
"example": "<ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel>Painel 1</ResizablePanel>\n <ResizableHandle />\n <ResizablePanel>Painel 2</ResizablePanel>\n</ResizablePanelGroup>",
|
|
1742
|
+
"keywords": [
|
|
1743
|
+
"resizable",
|
|
1744
|
+
"redimensionar",
|
|
1745
|
+
"painel",
|
|
1746
|
+
"split",
|
|
1747
|
+
"dividir",
|
|
1748
|
+
"drag"
|
|
1749
|
+
]
|
|
1750
|
+
},
|
|
1751
|
+
{
|
|
1752
|
+
"name": "Empty",
|
|
1753
|
+
"import": "import { Empty, EmptyIcon, EmptyTitle, EmptyDescription, EmptyContent } from \"@fluencypassdevs/cycle\"",
|
|
1754
|
+
"description": "Estado vazio com icone/media, titulo, descricao e area para acoes.",
|
|
1755
|
+
"props": [],
|
|
1756
|
+
"example": "<Empty>\n <EmptyIcon><CycleIcon icon={Inbox} size=\"lg\" decorative /></EmptyIcon>\n <EmptyTitle>Nenhum resultado</EmptyTitle>\n <EmptyDescription>Tente ajustar os filtros.</EmptyDescription>\n <EmptyContent><Button>Limpar filtros</Button></EmptyContent>\n</Empty>",
|
|
1757
|
+
"keywords": [
|
|
1758
|
+
"empty",
|
|
1759
|
+
"vazio",
|
|
1760
|
+
"nenhum",
|
|
1761
|
+
"resultado",
|
|
1762
|
+
"placeholder",
|
|
1763
|
+
"estado"
|
|
1764
|
+
]
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
"name": "Skeleton",
|
|
1768
|
+
"import": "import { Skeleton } from \"@fluencypassdevs/cycle\"",
|
|
1769
|
+
"description": "Placeholder animado (pulse) para conteudo em carregamento.",
|
|
1770
|
+
"props": [],
|
|
1771
|
+
"example": "<Skeleton className=\"h-4 w-[250px]\" />\n<Skeleton className=\"h-12 w-12 rounded-full\" />",
|
|
1772
|
+
"keywords": [
|
|
1773
|
+
"skeleton",
|
|
1774
|
+
"loading",
|
|
1775
|
+
"carregando",
|
|
1776
|
+
"placeholder",
|
|
1777
|
+
"shimmer",
|
|
1778
|
+
"pulse"
|
|
1779
|
+
]
|
|
1780
|
+
},
|
|
1781
|
+
{
|
|
1782
|
+
"name": "Spinner",
|
|
1783
|
+
"import": "import { Spinner } from \"@fluencypassdevs/cycle\"",
|
|
1784
|
+
"description": "Indicador de carregamento animado (spin). 5 sizes (xs, sm, default, lg, xl). Usa CycleIcon internamente. text-current herda cor do pai.",
|
|
1785
|
+
"props": [
|
|
1786
|
+
{
|
|
1787
|
+
"name": "size",
|
|
1788
|
+
"type": "\"xs\" | \"sm\" | \"default\" | \"lg\" | \"xl\"",
|
|
1789
|
+
"default": "\"sm\""
|
|
1790
|
+
},
|
|
1791
|
+
{
|
|
1792
|
+
"name": "label",
|
|
1793
|
+
"type": "string",
|
|
1794
|
+
"default": "\"Carregando\""
|
|
1795
|
+
}
|
|
1796
|
+
],
|
|
1797
|
+
"example": "<Spinner />\n<Spinner size=\"lg\" />\n<Button disabled><Spinner size=\"xs\" /> Salvando...</Button>",
|
|
1798
|
+
"keywords": [
|
|
1799
|
+
"spinner",
|
|
1800
|
+
"loading",
|
|
1801
|
+
"carregando",
|
|
1802
|
+
"aguarde",
|
|
1803
|
+
"loader",
|
|
1804
|
+
"spin",
|
|
1805
|
+
"indicador"
|
|
1806
|
+
]
|
|
1807
|
+
},
|
|
1808
|
+
{
|
|
1809
|
+
"name": "Dialog",
|
|
1810
|
+
"import": "import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from \"@fluencypassdevs/cycle\"",
|
|
1811
|
+
"description": "Modal dialog com overlay, close button, header/footer, titulo/descricao. Controlado ou via trigger.",
|
|
1812
|
+
"props": [
|
|
1813
|
+
{
|
|
1814
|
+
"name": "showCloseButton",
|
|
1815
|
+
"type": "boolean",
|
|
1816
|
+
"default": "true"
|
|
1817
|
+
}
|
|
1818
|
+
],
|
|
1819
|
+
"example": "<Dialog>\n <DialogTrigger asChild><Button>Abrir</Button></DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Titulo</DialogTitle>\n <DialogDescription>Descricao do modal.</DialogDescription>\n </DialogHeader>\n Conteudo\n <DialogFooter>\n <Button>Salvar</Button>\n </DialogFooter>\n </DialogContent>\n</Dialog>",
|
|
1820
|
+
"keywords": [
|
|
1821
|
+
"dialog",
|
|
1822
|
+
"modal",
|
|
1823
|
+
"popup",
|
|
1824
|
+
"janela",
|
|
1825
|
+
"overlay",
|
|
1826
|
+
"formulario"
|
|
1827
|
+
]
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
"name": "Fab",
|
|
1831
|
+
"import": "import { Fab } from \"@fluencypassdevs/cycle\"",
|
|
1832
|
+
"description": "Floating Action Button — botao circular flutuante para acao principal. 3 sizes (sm=40px, default=48px, lg=56px), 3 variants (default, secondary, outline). Modo extended (pill com icone + texto). Shadow-lg, posicao fixa configuravel.",
|
|
1833
|
+
"props": [
|
|
1834
|
+
{
|
|
1835
|
+
"name": "variant",
|
|
1836
|
+
"type": "\"default\" | \"secondary\" | \"outline\"",
|
|
1837
|
+
"default": "\"default\""
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
"name": "size",
|
|
1841
|
+
"type": "\"sm\" | \"default\" | \"lg\"",
|
|
1842
|
+
"default": "\"default\""
|
|
1843
|
+
},
|
|
1844
|
+
{
|
|
1845
|
+
"name": "extended",
|
|
1846
|
+
"type": "boolean",
|
|
1847
|
+
"default": "false"
|
|
1848
|
+
},
|
|
1849
|
+
{
|
|
1850
|
+
"name": "position",
|
|
1851
|
+
"type": "\"bottom-right\" | \"bottom-left\" | \"bottom-center\" | \"none\"",
|
|
1852
|
+
"default": "\"bottom-right\""
|
|
1853
|
+
},
|
|
1854
|
+
{
|
|
1855
|
+
"name": "asChild",
|
|
1856
|
+
"type": "boolean",
|
|
1857
|
+
"default": "false"
|
|
1858
|
+
}
|
|
1859
|
+
],
|
|
1860
|
+
"example": "<Fab position=\"none\" aria-label=\"Adicionar\">\n <CycleIcon icon={Plus} decorative />\n</Fab>\n<Fab extended position=\"none\">\n <CycleIcon icon={Pencil} decorative /> Editar\n</Fab>\n<Fab variant=\"secondary\" position=\"bottom-right\" aria-label=\"Chat\">\n <CycleIcon icon={MessageCircle} decorative />\n</Fab>",
|
|
1861
|
+
"keywords": [
|
|
1862
|
+
"fab",
|
|
1863
|
+
"floating",
|
|
1864
|
+
"action",
|
|
1865
|
+
"button",
|
|
1866
|
+
"botao",
|
|
1867
|
+
"flutuante",
|
|
1868
|
+
"circular",
|
|
1869
|
+
"shadow"
|
|
1870
|
+
]
|
|
1871
|
+
},
|
|
1872
|
+
{
|
|
1873
|
+
"name": "Drawer",
|
|
1874
|
+
"import": "import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from \"@fluencypassdevs/cycle\"",
|
|
1875
|
+
"description": "Bottom sheet com gesto de arraste (vaul). Ideal para mobile/touch. Handle de arraste automatico no bottom. Suporta 4 direcoes (top, right, bottom, left).",
|
|
1876
|
+
"props": [
|
|
1877
|
+
{
|
|
1878
|
+
"name": "direction",
|
|
1879
|
+
"type": "\"top\" | \"right\" | \"bottom\" | \"left\"",
|
|
1880
|
+
"default": "\"bottom\""
|
|
1881
|
+
},
|
|
1882
|
+
{
|
|
1883
|
+
"name": "open",
|
|
1884
|
+
"type": "boolean",
|
|
1885
|
+
"default": "undefined"
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
"name": "onOpenChange",
|
|
1889
|
+
"type": "(open: boolean) => void",
|
|
1890
|
+
"default": "undefined"
|
|
1891
|
+
}
|
|
1892
|
+
],
|
|
1893
|
+
"example": "<Drawer>\n <DrawerTrigger asChild>\n <Button>Abrir</Button>\n </DrawerTrigger>\n <DrawerContent>\n <DrawerHeader>\n <DrawerTitle>Acoes</DrawerTitle>\n <DrawerDescription>Escolha uma acao</DrawerDescription>\n </DrawerHeader>\n <div className=\"p-4 flex flex-col gap-2\">\n <Button variant=\"ghost\">Editar</Button>\n <Button variant=\"ghost\">Compartilhar</Button>\n </div>\n <DrawerFooter>\n <DrawerClose asChild>\n <Button variant=\"outline\">Cancelar</Button>\n </DrawerClose>\n </DrawerFooter>\n </DrawerContent>\n</Drawer>",
|
|
1894
|
+
"keywords": [
|
|
1895
|
+
"drawer",
|
|
1896
|
+
"bottom",
|
|
1897
|
+
"sheet",
|
|
1898
|
+
"action",
|
|
1899
|
+
"mobile",
|
|
1900
|
+
"arraste",
|
|
1901
|
+
"swipe",
|
|
1902
|
+
"vaul"
|
|
1903
|
+
]
|
|
1904
|
+
},
|
|
1905
|
+
{
|
|
1906
|
+
"name": "Editor",
|
|
1907
|
+
"import": "import { Editor } from \"@fluencypassdevs/cycle\"\nimport type { EditorRef } from \"@fluencypassdevs/cycle\"",
|
|
1908
|
+
"description": "Rich text editor (Tiptap/ProseMirror). Toolbar com undo/redo, bold, italic, underline, strikethrough, H2, bullet list e ordered list — botoes via Toggle + Tooltip + CycleIcon, com scroll horizontal no mobile. Visual alinhado ao Textarea outline. Prop toolbarTheme aplica tema na toolbar (ex: theme-class). Controlled/uncontrolled via content/defaultContent. Placeholder, editable, maxHeight/minHeight, resizable. forwardRef com EditorRef (editor/getHTML/getText/clear/focus).",
|
|
1909
|
+
"props": [
|
|
1910
|
+
{
|
|
1911
|
+
"name": "content / defaultContent",
|
|
1912
|
+
"type": "string (HTML)",
|
|
1913
|
+
"default": "-"
|
|
1914
|
+
},
|
|
1915
|
+
{
|
|
1916
|
+
"name": "placeholder",
|
|
1917
|
+
"type": "string",
|
|
1918
|
+
"default": "-"
|
|
1919
|
+
},
|
|
1920
|
+
{
|
|
1921
|
+
"name": "editable",
|
|
1922
|
+
"type": "boolean",
|
|
1923
|
+
"default": "true"
|
|
1924
|
+
},
|
|
1925
|
+
{
|
|
1926
|
+
"name": "toolbarTheme",
|
|
1927
|
+
"type": "string",
|
|
1928
|
+
"default": "-"
|
|
1929
|
+
},
|
|
1930
|
+
{
|
|
1931
|
+
"name": "maxHeight / minHeight",
|
|
1932
|
+
"type": "number",
|
|
1933
|
+
"default": "-"
|
|
1934
|
+
},
|
|
1935
|
+
{
|
|
1936
|
+
"name": "resizable",
|
|
1937
|
+
"type": "boolean",
|
|
1938
|
+
"default": "false"
|
|
1939
|
+
},
|
|
1940
|
+
{
|
|
1941
|
+
"name": "onChange",
|
|
1942
|
+
"type": "(html: string) => void",
|
|
1943
|
+
"default": "-"
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
"name": "ref",
|
|
1947
|
+
"type": "React.Ref<EditorRef>",
|
|
1948
|
+
"default": "-"
|
|
1949
|
+
}
|
|
1950
|
+
],
|
|
1951
|
+
"example": "<Editor\n defaultContent=\"<p>Descreva a atividade...</p>\"\n placeholder=\"Escreva aqui\"\n toolbarTheme=\"theme-class\"\n onChange={(html) => setDescricao(html)}\n/>",
|
|
1952
|
+
"keywords": [
|
|
1953
|
+
"editor",
|
|
1954
|
+
"rich text",
|
|
1955
|
+
"tiptap",
|
|
1956
|
+
"wysiwyg",
|
|
1957
|
+
"texto formatado",
|
|
1958
|
+
"descricao",
|
|
1959
|
+
"toolbar",
|
|
1960
|
+
"prosemirror"
|
|
1961
|
+
]
|
|
1962
|
+
},
|
|
1963
|
+
{
|
|
1964
|
+
"name": "Separator",
|
|
1965
|
+
"import": "import { Separator } from \"@fluencypassdevs/cycle\"",
|
|
1966
|
+
"description": "Linha divisoria horizontal ou vertical acessivel (Radix), usando o token bg-border. Decorative por padrao.",
|
|
1967
|
+
"props": [
|
|
1968
|
+
{
|
|
1969
|
+
"name": "orientation",
|
|
1970
|
+
"type": "\"horizontal\" | \"vertical\"",
|
|
1971
|
+
"default": "\"horizontal\""
|
|
1972
|
+
},
|
|
1973
|
+
{
|
|
1974
|
+
"name": "decorative",
|
|
1975
|
+
"type": "boolean",
|
|
1976
|
+
"default": "true"
|
|
1977
|
+
}
|
|
1978
|
+
],
|
|
1979
|
+
"example": "<Separator />\n<div className=\"flex h-5 items-center gap-4\">\n <span>Docs</span>\n <Separator orientation=\"vertical\" />\n <span>Componentes</span>\n</div>",
|
|
1980
|
+
"keywords": [
|
|
1981
|
+
"separator",
|
|
1982
|
+
"divisor",
|
|
1983
|
+
"divider",
|
|
1984
|
+
"linha",
|
|
1985
|
+
"hr",
|
|
1986
|
+
"secao"
|
|
1987
|
+
]
|
|
1988
|
+
},
|
|
1989
|
+
{
|
|
1990
|
+
"name": "Collapsible",
|
|
1991
|
+
"import": "import { Collapsible, CollapsibleTrigger, CollapsibleContent } from \"@fluencypassdevs/cycle\"",
|
|
1992
|
+
"description": "Regiao expansivel/recolhivel sem estilo imposto (Radix). Primitivo para secoes opcionais de formulario — para listas estilizadas use Accordion.",
|
|
1993
|
+
"props": [
|
|
1994
|
+
{
|
|
1995
|
+
"name": "defaultOpen",
|
|
1996
|
+
"type": "boolean",
|
|
1997
|
+
"default": "false"
|
|
1998
|
+
},
|
|
1999
|
+
{
|
|
2000
|
+
"name": "open",
|
|
2001
|
+
"type": "boolean",
|
|
2002
|
+
"default": "-"
|
|
2003
|
+
},
|
|
2004
|
+
{
|
|
2005
|
+
"name": "onOpenChange",
|
|
2006
|
+
"type": "(open: boolean) => void",
|
|
2007
|
+
"default": "-"
|
|
2008
|
+
},
|
|
2009
|
+
{
|
|
2010
|
+
"name": "disabled",
|
|
2011
|
+
"type": "boolean",
|
|
2012
|
+
"default": "false"
|
|
2013
|
+
}
|
|
2014
|
+
],
|
|
2015
|
+
"example": "<Collapsible>\n <CollapsibleTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\">Opcoes avancadas</Button>\n </CollapsibleTrigger>\n <CollapsibleContent>Campos opcionais aqui</CollapsibleContent>\n</Collapsible>",
|
|
2016
|
+
"keywords": [
|
|
2017
|
+
"collapsible",
|
|
2018
|
+
"colapsavel",
|
|
2019
|
+
"expandir",
|
|
2020
|
+
"recolher",
|
|
2021
|
+
"toggle",
|
|
2022
|
+
"secao opcional",
|
|
2023
|
+
"avancado"
|
|
2024
|
+
]
|
|
2025
|
+
},
|
|
2026
|
+
{
|
|
2027
|
+
"name": "Card",
|
|
2028
|
+
"import": "import { Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter } from \"@fluencypassdevs/cycle\"",
|
|
2029
|
+
"description": "Container de superficie com header, titulo, descricao, acao, conteudo e rodape. bg-card, border, rounded-xl, shadow-sm.",
|
|
2030
|
+
"props": [
|
|
2031
|
+
{
|
|
2032
|
+
"name": "className",
|
|
2033
|
+
"type": "string",
|
|
2034
|
+
"default": "-"
|
|
2035
|
+
}
|
|
2036
|
+
],
|
|
2037
|
+
"example": "<Card>\n <CardHeader>\n <CardTitle>Titulo</CardTitle>\n <CardDescription>Descricao do card</CardDescription>\n <CardAction><Badge variant=\"secondary\">Novo</Badge></CardAction>\n </CardHeader>\n <CardContent>Conteudo</CardContent>\n <CardFooter><Button size=\"sm\">Salvar</Button></CardFooter>\n</Card>",
|
|
2038
|
+
"keywords": [
|
|
2039
|
+
"card",
|
|
2040
|
+
"cartao",
|
|
2041
|
+
"container",
|
|
2042
|
+
"superficie",
|
|
2043
|
+
"painel",
|
|
2044
|
+
"bloco",
|
|
2045
|
+
"agrupamento"
|
|
2046
|
+
]
|
|
2047
|
+
},
|
|
2048
|
+
{
|
|
2049
|
+
"name": "Breadcrumb",
|
|
2050
|
+
"import": "import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis, BreadcrumbDot, BreadcrumbSwitcherTrigger } from \"@fluencypassdevs/cycle\"",
|
|
2051
|
+
"description": "Trilha de navegacao hierarquica com links, item atual (aria-current), separador ChevronRight (via CycleIcon) e ellipsis para caminhos longos. BreadcrumbLink aceita asChild para Next Link. Para hierarquias profundas: BreadcrumbDot (bullet que codifica o nivel por cor via prop theme, ex theme-class) e BreadcrumbSwitcherTrigger (gatilho do dropdown de troca de irmaos do mesmo nivel — usar dentro de DropdownMenuTrigger asChild, sempre com aria-label; so mostrar quando ha mais de um irmao).",
|
|
2052
|
+
"props": [
|
|
2053
|
+
{
|
|
2054
|
+
"name": "asChild (BreadcrumbLink)",
|
|
2055
|
+
"type": "boolean",
|
|
2056
|
+
"default": "false"
|
|
2057
|
+
},
|
|
2058
|
+
{
|
|
2059
|
+
"name": "theme (BreadcrumbDot)",
|
|
2060
|
+
"type": "string",
|
|
2061
|
+
"default": "-",
|
|
2062
|
+
"note": "classe de tema que colore o dot (ex: theme-class, theme-group)"
|
|
2063
|
+
},
|
|
2064
|
+
{
|
|
2065
|
+
"name": "aria-label (BreadcrumbSwitcherTrigger)",
|
|
2066
|
+
"type": "string",
|
|
2067
|
+
"default": "-",
|
|
2068
|
+
"note": "obrigatoria — descreve a troca (ex: 'Trocar de curso')"
|
|
2069
|
+
}
|
|
2070
|
+
],
|
|
2071
|
+
"example": "<Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink href=\"/trilhas\">Trilhas</BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbDot theme=\"theme-class\" />\n <BreadcrumbLink href=\"/cursos/ingles\">Ingles Corporativo</BreadcrumbLink>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <BreadcrumbSwitcherTrigger aria-label=\"Trocar de curso\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent>{/* irmaos do nivel */}</DropdownMenuContent>\n </DropdownMenu>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>Modulo 3</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n</Breadcrumb>",
|
|
2072
|
+
"keywords": [
|
|
2073
|
+
"breadcrumb",
|
|
2074
|
+
"navegacao",
|
|
2075
|
+
"trilha",
|
|
2076
|
+
"hierarquia",
|
|
2077
|
+
"caminho",
|
|
2078
|
+
"migalha",
|
|
2079
|
+
"dot",
|
|
2080
|
+
"nivel",
|
|
2081
|
+
"switcher",
|
|
2082
|
+
"irmaos",
|
|
2083
|
+
"trocar"
|
|
2084
|
+
]
|
|
2085
|
+
},
|
|
2086
|
+
{
|
|
2087
|
+
"name": "Table",
|
|
2088
|
+
"import": "import { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from \"@fluencypassdevs/cycle\"",
|
|
2089
|
+
"description": "Tabela de dados para listagens (admin: cursos, alunos, transacoes). Wrapper com overflow-x proprio — tabela larga rola no container, nunca a pagina. Hover de linha, estado selecionado via data-state=selected, celula com checkbox remove padding direito automaticamente. UI-only: sort, filtro, paginacao e logica de selecao ficam no consumidor (GOVERNANCE.md Fronteiras de escopo). Colunas numericas: text-right + tabular-nums.",
|
|
2090
|
+
"props": [],
|
|
2091
|
+
"example": "<Table>\n <TableCaption>Cursos ativos.</TableCaption>\n <TableHeader>\n <TableRow>\n <TableHead>Curso</TableHead>\n <TableHead className=\"text-right\">Alunos</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {cursos.map((c) => (\n <TableRow key={c.id} data-state={c.selecionado ? \"selected\" : undefined}>\n <TableCell className=\"font-medium\">{c.nome}</TableCell>\n <TableCell className=\"text-right tabular-nums\">{c.alunos}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n</Table>",
|
|
2092
|
+
"keywords": [
|
|
2093
|
+
"table",
|
|
2094
|
+
"tabela",
|
|
2095
|
+
"listagem",
|
|
2096
|
+
"lista",
|
|
2097
|
+
"dados",
|
|
2098
|
+
"admin",
|
|
2099
|
+
"grid de dados",
|
|
2100
|
+
"linhas",
|
|
2101
|
+
"colunas"
|
|
2102
|
+
]
|
|
2103
|
+
},
|
|
2104
|
+
{
|
|
2105
|
+
"name": "Pagination",
|
|
2106
|
+
"import": "import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationEllipsis } from \"@fluencypassdevs/cycle\"",
|
|
2107
|
+
"description": "Navegacao de paginas para listagens (par natural do Table). PaginationLink com isActive (outline + aria-current=page) e asChild para Next Link. PaginationPrevious/Next com chevrons via CycleIcon e labels PT-BR customizaveis (prop label); texto some no mobile. UI-only: a janela de paginas (quais numeros mostrar, quando usar ellipsis) fica no consumidor.",
|
|
2108
|
+
"props": [
|
|
2109
|
+
{
|
|
2110
|
+
"name": "isActive (PaginationLink)",
|
|
2111
|
+
"type": "boolean",
|
|
2112
|
+
"default": "false"
|
|
2113
|
+
},
|
|
2114
|
+
{
|
|
2115
|
+
"name": "asChild (PaginationLink)",
|
|
2116
|
+
"type": "boolean",
|
|
2117
|
+
"default": "false"
|
|
2118
|
+
},
|
|
2119
|
+
{
|
|
2120
|
+
"name": "size (PaginationLink)",
|
|
2121
|
+
"type": "\"icon-sm\" | \"icon\" | \"sm\" | \"default\"",
|
|
2122
|
+
"default": "\"icon-sm\""
|
|
2123
|
+
},
|
|
2124
|
+
{
|
|
2125
|
+
"name": "label (Previous/Next/Ellipsis)",
|
|
2126
|
+
"type": "string",
|
|
2127
|
+
"default": "\"Anterior\" / \"Próxima\" / \"Mais páginas\""
|
|
2128
|
+
}
|
|
2129
|
+
],
|
|
2130
|
+
"example": "<Pagination>\n <PaginationContent>\n <PaginationItem><PaginationPrevious href=\"?page=1\" /></PaginationItem>\n <PaginationItem>\n <PaginationLink asChild isActive={page === 2}>\n <Link href=\"?page=2\">2</Link>\n </PaginationLink>\n </PaginationItem>\n <PaginationItem><PaginationEllipsis /></PaginationItem>\n <PaginationItem><PaginationNext href=\"?page=3\" /></PaginationItem>\n </PaginationContent>\n</Pagination>",
|
|
2131
|
+
"keywords": [
|
|
2132
|
+
"pagination",
|
|
2133
|
+
"paginacao",
|
|
2134
|
+
"paginas",
|
|
2135
|
+
"navegar",
|
|
2136
|
+
"listagem",
|
|
2137
|
+
"anterior",
|
|
2138
|
+
"proxima",
|
|
2139
|
+
"ellipsis"
|
|
2140
|
+
]
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
"name": "Command (Combobox)",
|
|
2144
|
+
"import": "import { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut } from \"@fluencypassdevs/cycle\"",
|
|
2145
|
+
"description": "Lista de comandos com busca (cmdk). Base do padrao Combobox: Popover + Command + Button trigger (role=combobox, aria-expanded). CommandDialog para paleta Cmd+K. Filtro fuzzy embutido; shouldFilter={false} para busca assincrona (filtro no servidor, itens renderizados = resultado). UI-only: debounce, cache e estado de selecao ficam no consumidor. Lista curta sem busca → usar Select.",
|
|
2146
|
+
"props": [
|
|
2147
|
+
{
|
|
2148
|
+
"name": "shouldFilter (Command)",
|
|
2149
|
+
"type": "boolean",
|
|
2150
|
+
"default": "true"
|
|
2151
|
+
},
|
|
2152
|
+
{
|
|
2153
|
+
"name": "value/keywords (CommandItem)",
|
|
2154
|
+
"type": "string / string[]",
|
|
2155
|
+
"default": "-"
|
|
2156
|
+
},
|
|
2157
|
+
{
|
|
2158
|
+
"name": "onSelect (CommandItem)",
|
|
2159
|
+
"type": "(value: string) => void",
|
|
2160
|
+
"default": "-"
|
|
2161
|
+
}
|
|
2162
|
+
],
|
|
2163
|
+
"example": "<Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"outline\" role=\"combobox\" aria-expanded={open} className=\"w-64 justify-between font-normal\">\n {value ? cursos.find((c) => c.value === value)?.label : \"Selecionar curso...\"}\n <CycleIcon icon={ChevronsUpDown} size=\"sm\" decorative className=\"opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-0\">\n <Command>\n <CommandInput placeholder=\"Buscar curso...\" />\n <CommandList>\n <CommandEmpty>Nenhum curso encontrado.</CommandEmpty>\n <CommandGroup>\n {cursos.map((c) => (\n <CommandItem key={c.value} value={c.value} keywords={[c.label]}\n onSelect={(v) => { setValue(v); setOpen(false) }}>\n {c.label}\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n</Popover>",
|
|
2164
|
+
"keywords": [
|
|
2165
|
+
"combobox",
|
|
2166
|
+
"command",
|
|
2167
|
+
"busca",
|
|
2168
|
+
"autocomplete",
|
|
2169
|
+
"search",
|
|
2170
|
+
"select com busca",
|
|
2171
|
+
"cmdk",
|
|
2172
|
+
"paleta",
|
|
2173
|
+
"cmd+k",
|
|
2174
|
+
"filtrar"
|
|
2175
|
+
]
|
|
2176
|
+
},
|
|
2177
|
+
{
|
|
2178
|
+
"name": "Stepper",
|
|
2179
|
+
"import": "import { Stepper } from \"@fluencypassdevs/cycle\"\nimport type { StepperStep } from \"@fluencypassdevs/cycle\"",
|
|
2180
|
+
"description": "Indicador de etapas com rotulos para fluxos multi-step (criacao de curso, onboarding, checkout). 4 estados: completed (Check), current (aria-current=step), upcoming, error (X destructive). Orientacao horizontal (desktop) e vertical (mobile/sidebar). Prop theme aplica cor so nos estados ativos, como na familia progress. onStepClick torna apenas etapas CONCLUIDAS clicaveis — pular pra frente e validacao ficam no consumidor. Progresso sem rotulos → ProgressStage/ProgressDot.",
|
|
2181
|
+
"props": [
|
|
2182
|
+
{
|
|
2183
|
+
"name": "steps",
|
|
2184
|
+
"type": "StepperStep[] ({ label, description? })",
|
|
2185
|
+
"default": "-"
|
|
2186
|
+
},
|
|
2187
|
+
{
|
|
2188
|
+
"name": "currentStep",
|
|
2189
|
+
"type": "number (0-based)",
|
|
2190
|
+
"default": "-"
|
|
2191
|
+
},
|
|
2192
|
+
{
|
|
2193
|
+
"name": "errorSteps",
|
|
2194
|
+
"type": "number[]",
|
|
2195
|
+
"default": "-"
|
|
2196
|
+
},
|
|
2197
|
+
{
|
|
2198
|
+
"name": "orientation",
|
|
2199
|
+
"type": "\"horizontal\" | \"vertical\"",
|
|
2200
|
+
"default": "\"horizontal\""
|
|
2201
|
+
},
|
|
2202
|
+
{
|
|
2203
|
+
"name": "size",
|
|
2204
|
+
"type": "\"sm\" | \"default\"",
|
|
2205
|
+
"default": "\"default\""
|
|
2206
|
+
},
|
|
2207
|
+
{
|
|
2208
|
+
"name": "theme",
|
|
2209
|
+
"type": "string",
|
|
2210
|
+
"default": "-"
|
|
2211
|
+
},
|
|
2212
|
+
{
|
|
2213
|
+
"name": "onStepClick",
|
|
2214
|
+
"type": "(index: number) => void",
|
|
2215
|
+
"default": "-"
|
|
2216
|
+
}
|
|
2217
|
+
],
|
|
2218
|
+
"example": "<Stepper\n steps={[\n { label: \"Dados do curso\", description: \"Nome e descrição\" },\n { label: \"Unidades\" },\n { label: \"Revisão\", description: \"Publicar\" },\n ]}\n currentStep={1}\n theme=\"theme-class\"\n onStepClick={(i) => setCurrent(i)}\n/>",
|
|
2219
|
+
"keywords": [
|
|
2220
|
+
"stepper",
|
|
2221
|
+
"etapas",
|
|
2222
|
+
"passos",
|
|
2223
|
+
"wizard",
|
|
2224
|
+
"multi-step",
|
|
2225
|
+
"fluxo",
|
|
2226
|
+
"onboarding",
|
|
2227
|
+
"checkout",
|
|
2228
|
+
"progresso com rotulo"
|
|
2229
|
+
]
|
|
2230
|
+
},
|
|
2231
|
+
{
|
|
2232
|
+
"name": "FileDropzone",
|
|
2233
|
+
"import": "import { FileDropzone, FileDropzoneItem, formatFileSize } from \"@fluencypassdevs/cycle\"",
|
|
2234
|
+
"description": "Upload de arquivo UI-ONLY: area de drag-and-drop acessivel com validacao de SELECAO (accept MIME/extensao, tamanho maximo, arquivo de 0 bytes, quantidade) e mensagens PT-BR customizaveis. O upload em si (fetch, presigned URL, storage R2/Cloudinary) fica no CONSUMIDOR: onFilesAccepted entrega os Files validados e o progresso volta pelo FileDropzoneItem (status uploading/success/error + progress 0-100). Cada rejeicao dispara onFileRejected(file, reason). GOVERNANCE Fronteiras de escopo.",
|
|
2235
|
+
"props": [
|
|
2236
|
+
{
|
|
2237
|
+
"name": "accept",
|
|
2238
|
+
"type": "string (sintaxe input nativo)",
|
|
2239
|
+
"default": "-"
|
|
2240
|
+
},
|
|
2241
|
+
{
|
|
2242
|
+
"name": "maxSize",
|
|
2243
|
+
"type": "number (bytes)",
|
|
2244
|
+
"default": "-"
|
|
2245
|
+
},
|
|
2246
|
+
{
|
|
2247
|
+
"name": "multiple / maxFiles",
|
|
2248
|
+
"type": "boolean / number",
|
|
2249
|
+
"default": "false / -"
|
|
2250
|
+
},
|
|
2251
|
+
{
|
|
2252
|
+
"name": "onFilesAccepted",
|
|
2253
|
+
"type": "(files: File[]) => void",
|
|
2254
|
+
"default": "-"
|
|
2255
|
+
},
|
|
2256
|
+
{
|
|
2257
|
+
"name": "onFileRejected",
|
|
2258
|
+
"type": "(file, reason: \"type\"|\"size\"|\"empty\"|\"count\") => void",
|
|
2259
|
+
"default": "-"
|
|
2260
|
+
},
|
|
2261
|
+
{
|
|
2262
|
+
"name": "labels",
|
|
2263
|
+
"type": "{ instruction?, hint?, errors? }",
|
|
2264
|
+
"default": "PT-BR"
|
|
2265
|
+
},
|
|
2266
|
+
{
|
|
2267
|
+
"name": "status (Item)",
|
|
2268
|
+
"type": "\"idle\"|\"uploading\"|\"success\"|\"error\"",
|
|
2269
|
+
"default": "\"idle\""
|
|
2270
|
+
},
|
|
2271
|
+
{
|
|
2272
|
+
"name": "progress (Item)",
|
|
2273
|
+
"type": "number 0-100",
|
|
2274
|
+
"default": "-"
|
|
2275
|
+
}
|
|
2276
|
+
],
|
|
2277
|
+
"example": "<FileDropzone\n accept=\"audio/*,.mp3,.wav\"\n maxSize={20 * 1024 * 1024}\n labels={{ hint: \"MP3 ou WAV até 20 MB\" }}\n onFilesAccepted={(files) => iniciarUpload(files)}\n/>\n{arquivos.map((f) => (\n <FileDropzoneItem key={f.id} name={f.name} size={f.size}\n status={f.status} progress={f.progress} onRemove={() => remover(f.id)} />\n))}",
|
|
2278
|
+
"keywords": [
|
|
2279
|
+
"upload",
|
|
2280
|
+
"arquivo",
|
|
2281
|
+
"dropzone",
|
|
2282
|
+
"drag and drop",
|
|
2283
|
+
"arrastar",
|
|
2284
|
+
"file",
|
|
2285
|
+
"anexo",
|
|
2286
|
+
"selecionar arquivo",
|
|
2287
|
+
"enviar arquivo"
|
|
2288
|
+
]
|
|
2289
|
+
},
|
|
2290
|
+
{
|
|
2291
|
+
"name": "RevealOnScroll",
|
|
2292
|
+
"import": "import { RevealOnScroll } from \"@fluencypassdevs/cycle/marketing/motion/reveal-on-scroll\"",
|
|
2293
|
+
"description": "MARKETING (landing pages). Wrapper que aplica fade-up suave (translateY 8px + opacity 0->1, 720ms) quando o elemento entra no viewport. Usa IntersectionObserver. Respeita prefers-reduced-motion (entrega visivel sem transicao). Compoe com qualquer conteudo via children.",
|
|
2294
|
+
"props": [
|
|
2295
|
+
{
|
|
2296
|
+
"name": "as",
|
|
2297
|
+
"type": "\"div\" | \"section\" | \"article\" | \"header\" | \"footer\" | \"main\" | \"aside\"",
|
|
2298
|
+
"default": "\"div\""
|
|
2299
|
+
},
|
|
2300
|
+
{
|
|
2301
|
+
"name": "delay",
|
|
2302
|
+
"type": "number",
|
|
2303
|
+
"default": "0",
|
|
2304
|
+
"note": "delay extra antes da animacao (ms)"
|
|
2305
|
+
},
|
|
2306
|
+
{
|
|
2307
|
+
"name": "threshold",
|
|
2308
|
+
"type": "number",
|
|
2309
|
+
"default": "0.15",
|
|
2310
|
+
"note": "fracao do elemento visivel pra disparar (0-1)"
|
|
2311
|
+
},
|
|
2312
|
+
{
|
|
2313
|
+
"name": "rootMargin",
|
|
2314
|
+
"type": "string",
|
|
2315
|
+
"default": "\"0px 0px -10% 0px\"",
|
|
2316
|
+
"note": "margin do viewport (CSS shorthand)"
|
|
2317
|
+
},
|
|
2318
|
+
{
|
|
2319
|
+
"name": "repeat",
|
|
2320
|
+
"type": "boolean",
|
|
2321
|
+
"default": "false",
|
|
2322
|
+
"note": "reanima toda vez que reentrar no viewport"
|
|
2323
|
+
}
|
|
2324
|
+
],
|
|
2325
|
+
"example": "<RevealOnScroll>\n <h2>Aparece com fade-up</h2>\n</RevealOnScroll>\n\n<RevealOnScroll as=\"section\" delay={200}>\n <Card>Atrasa 200ms a entrada</Card>\n</RevealOnScroll>",
|
|
2326
|
+
"keywords": [
|
|
2327
|
+
"marketing",
|
|
2328
|
+
"landing",
|
|
2329
|
+
"motion",
|
|
2330
|
+
"animation",
|
|
2331
|
+
"scroll",
|
|
2332
|
+
"fade",
|
|
2333
|
+
"reveal",
|
|
2334
|
+
"entrada"
|
|
2335
|
+
]
|
|
2336
|
+
},
|
|
2337
|
+
{
|
|
2338
|
+
"name": "StaggerReveal",
|
|
2339
|
+
"import": "import { StaggerReveal } from \"@fluencypassdevs/cycle/marketing/motion/stagger-reveal\"",
|
|
2340
|
+
"description": "MARKETING (landing pages). Container que anima seus filhos em sequencia (fade-up com delay incremental). Clona cada filho via React.Children.map e injeta --stagger-index como CSS var; animacao acontece via .stagger-child no globals.css. Util pra grids de cards, listas de features, secao de pilares. Respeita prefers-reduced-motion.",
|
|
2341
|
+
"props": [
|
|
2342
|
+
{
|
|
2343
|
+
"name": "step",
|
|
2344
|
+
"type": "number",
|
|
2345
|
+
"default": "100",
|
|
2346
|
+
"note": "delay entre cada filho (ms)"
|
|
2347
|
+
},
|
|
2348
|
+
{
|
|
2349
|
+
"name": "threshold",
|
|
2350
|
+
"type": "number",
|
|
2351
|
+
"default": "0.15",
|
|
2352
|
+
"note": "fracao do container visivel pra disparar"
|
|
2353
|
+
},
|
|
2354
|
+
{
|
|
2355
|
+
"name": "rootMargin",
|
|
2356
|
+
"type": "string",
|
|
2357
|
+
"default": "\"0px 0px -10% 0px\""
|
|
2358
|
+
}
|
|
2359
|
+
],
|
|
2360
|
+
"example": "<StaggerReveal step={120} className=\"grid grid-cols-3 gap-3\">\n <Card>1</Card>\n <Card>2</Card>\n <Card>3</Card>\n</StaggerReveal>",
|
|
2361
|
+
"keywords": [
|
|
2362
|
+
"marketing",
|
|
2363
|
+
"landing",
|
|
2364
|
+
"motion",
|
|
2365
|
+
"animation",
|
|
2366
|
+
"stagger",
|
|
2367
|
+
"sequencia",
|
|
2368
|
+
"cards",
|
|
2369
|
+
"grid"
|
|
2370
|
+
]
|
|
2371
|
+
},
|
|
2372
|
+
{
|
|
2373
|
+
"name": "AnimatedNumber",
|
|
2374
|
+
"import": "import { AnimatedNumber } from \"@fluencypassdevs/cycle/marketing/motion/animated-number\"",
|
|
2375
|
+
"description": "MARKETING (landing pages). Conta de `from` ate `value` com easing easeOutCubic ao entrar no viewport. Suporta prefix/suffix, decimals, locale (pt-BR ou plain). Aplica tabular-nums automaticamente pra largura estavel. Respeita prefers-reduced-motion (pula pro valor final).",
|
|
2376
|
+
"props": [
|
|
2377
|
+
{
|
|
2378
|
+
"name": "value",
|
|
2379
|
+
"type": "number",
|
|
2380
|
+
"default": "-",
|
|
2381
|
+
"note": "valor final (obrigatorio)"
|
|
2382
|
+
},
|
|
2383
|
+
{
|
|
2384
|
+
"name": "from",
|
|
2385
|
+
"type": "number",
|
|
2386
|
+
"default": "0"
|
|
2387
|
+
},
|
|
2388
|
+
{
|
|
2389
|
+
"name": "duration",
|
|
2390
|
+
"type": "number",
|
|
2391
|
+
"default": "1400",
|
|
2392
|
+
"note": "duracao da animacao (ms)"
|
|
2393
|
+
},
|
|
2394
|
+
{
|
|
2395
|
+
"name": "prefix",
|
|
2396
|
+
"type": "string",
|
|
2397
|
+
"default": "\"\"",
|
|
2398
|
+
"note": "ex: \"R$ \", \"+\""
|
|
2399
|
+
},
|
|
2400
|
+
{
|
|
2401
|
+
"name": "suffix",
|
|
2402
|
+
"type": "string",
|
|
2403
|
+
"default": "\"\"",
|
|
2404
|
+
"note": "ex: \"%\", \"k\""
|
|
2405
|
+
},
|
|
2406
|
+
{
|
|
2407
|
+
"name": "decimals",
|
|
2408
|
+
"type": "number",
|
|
2409
|
+
"default": "0"
|
|
2410
|
+
},
|
|
2411
|
+
{
|
|
2412
|
+
"name": "locale",
|
|
2413
|
+
"type": "\"pt-BR\" | \"plain\"",
|
|
2414
|
+
"default": "\"pt-BR\""
|
|
2415
|
+
},
|
|
2416
|
+
{
|
|
2417
|
+
"name": "threshold",
|
|
2418
|
+
"type": "number",
|
|
2419
|
+
"default": "0.4"
|
|
2420
|
+
}
|
|
2421
|
+
],
|
|
2422
|
+
"example": "<AnimatedNumber value={1247} suffix=\"+\" />\n<AnimatedNumber prefix=\"R$ \" value={3.5} decimals={1} suffix=\"M\" />\n<AnimatedNumber value={97} suffix=\"%\" />",
|
|
2423
|
+
"keywords": [
|
|
2424
|
+
"marketing",
|
|
2425
|
+
"landing",
|
|
2426
|
+
"motion",
|
|
2427
|
+
"counter",
|
|
2428
|
+
"number",
|
|
2429
|
+
"stats",
|
|
2430
|
+
"kpi",
|
|
2431
|
+
"metric"
|
|
2432
|
+
]
|
|
2433
|
+
},
|
|
2434
|
+
{
|
|
2435
|
+
"name": "SmoothAnchor",
|
|
2436
|
+
"import": "import { SmoothAnchor } from \"@fluencypassdevs/cycle/marketing/motion/smooth-anchor\"",
|
|
2437
|
+
"description": "MARKETING (landing pages). Intercepta cliques em links de hash (<a href=#X>) e faz scroll suave com easing easeInOutCubic em vez do scroll-behavior:smooth nativo. Monta UMA VEZ por app (no RootLayout). Renderiza null (so registra listener global). Pulsa destino apos chegar via .anchor-target-pulse. Respeita prefers-reduced-motion (scroll instantaneo).",
|
|
2438
|
+
"props": [
|
|
2439
|
+
{
|
|
2440
|
+
"name": "headerOffset",
|
|
2441
|
+
"type": "number",
|
|
2442
|
+
"default": "96",
|
|
2443
|
+
"note": "offset em px (compensar header sticky)"
|
|
2444
|
+
},
|
|
2445
|
+
{
|
|
2446
|
+
"name": "duration",
|
|
2447
|
+
"type": "number",
|
|
2448
|
+
"default": "900",
|
|
2449
|
+
"note": "duracao do scroll (ms)"
|
|
2450
|
+
}
|
|
2451
|
+
],
|
|
2452
|
+
"example": "// app/layout.tsx\n<body>\n <SmoothAnchor headerOffset={64} duration={900} />\n {children}\n</body>\n\n// Qualquer link de hash agora usa scroll suave:\n<a href=\"#solucao\">Ver solucao</a>\n<section id=\"solucao\" data-anchor-pulse>...</section>",
|
|
2453
|
+
"keywords": [
|
|
2454
|
+
"marketing",
|
|
2455
|
+
"landing",
|
|
2456
|
+
"motion",
|
|
2457
|
+
"scroll",
|
|
2458
|
+
"anchor",
|
|
2459
|
+
"hash",
|
|
2460
|
+
"navegacao",
|
|
2461
|
+
"suave"
|
|
2462
|
+
]
|
|
2463
|
+
},
|
|
2464
|
+
{
|
|
2465
|
+
"name": "Section",
|
|
2466
|
+
"import": "import { Section } from \"@fluencypassdevs/cycle/marketing/layout/section\"",
|
|
2467
|
+
"description": "MARKETING (landing pages) — Camada 2a. Wrapper de dobra. Padroniza padding/altura via variant (hero=min-h-screen flex flex-col, default=py-20 md:py-28) e alterna fundo via tone (dark default, light aplica .light-surface). Generaliza o HomeSection do site corporativo. Pareie com SectionHeading/Eyebrow/Subtitle.",
|
|
2468
|
+
"props": [
|
|
2469
|
+
{
|
|
2470
|
+
"name": "as",
|
|
2471
|
+
"type": "\"section\" | \"div\"",
|
|
2472
|
+
"default": "\"section\""
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
"name": "variant",
|
|
2476
|
+
"type": "\"hero\" | \"default\"",
|
|
2477
|
+
"default": "\"default\"",
|
|
2478
|
+
"note": "hero ocupa min-h-screen; default tem py generoso"
|
|
2479
|
+
},
|
|
2480
|
+
{
|
|
2481
|
+
"name": "tone",
|
|
2482
|
+
"type": "\"dark\" | \"light\"",
|
|
2483
|
+
"default": "\"dark\"",
|
|
2484
|
+
"note": "light aplica .light-surface (override de tokens semanticos)"
|
|
2485
|
+
},
|
|
2486
|
+
{
|
|
2487
|
+
"name": "id",
|
|
2488
|
+
"type": "string",
|
|
2489
|
+
"default": "-",
|
|
2490
|
+
"note": "ID para ancoragem via SmoothAnchor"
|
|
2491
|
+
}
|
|
2492
|
+
],
|
|
2493
|
+
"example": "<Section variant=\"hero\">\n <HeroHeading>Acelere o ingles do seu time</HeroHeading>\n</Section>\n\n<Section id=\"pilares\" variant=\"default\" tone=\"light\">\n <SectionEyebrow align=\"center\">Para empresas</SectionEyebrow>\n <SectionHeading>3 pilares essenciais</SectionHeading>\n <div className=\"grid md:grid-cols-3 gap-6\">{cards}</div>\n</Section>",
|
|
2494
|
+
"keywords": [
|
|
2495
|
+
"marketing",
|
|
2496
|
+
"landing",
|
|
2497
|
+
"layout",
|
|
2498
|
+
"section",
|
|
2499
|
+
"dobra",
|
|
2500
|
+
"wrapper",
|
|
2501
|
+
"hero"
|
|
2502
|
+
]
|
|
2503
|
+
},
|
|
2504
|
+
{
|
|
2505
|
+
"name": "HeroHeading",
|
|
2506
|
+
"import": "import { HeroHeading } from \"@fluencypassdevs/cycle/marketing/typography/hero-heading\"",
|
|
2507
|
+
"description": "MARKETING — Camada 2a. Titulo dramatico para hero (h1 default). Sizes grandes, font-bold, leading apertado (1.07), text-balance, max-w-2xl. Use no primeiro titulo da landing.",
|
|
2508
|
+
"props": [
|
|
2509
|
+
{
|
|
2510
|
+
"name": "as",
|
|
2511
|
+
"type": "\"h1\" | \"h2\" | \"div\"",
|
|
2512
|
+
"default": "\"h1\""
|
|
2513
|
+
},
|
|
2514
|
+
{
|
|
2515
|
+
"name": "align",
|
|
2516
|
+
"type": "\"left\" | \"center\"",
|
|
2517
|
+
"default": "\"left\""
|
|
2518
|
+
}
|
|
2519
|
+
],
|
|
2520
|
+
"example": "<HeroHeading>Acelere o ingles do seu time</HeroHeading>\n<HeroHeading align=\"center\">Aprenda rapido com IA</HeroHeading>",
|
|
2521
|
+
"keywords": [
|
|
2522
|
+
"marketing",
|
|
2523
|
+
"landing",
|
|
2524
|
+
"typography",
|
|
2525
|
+
"heading",
|
|
2526
|
+
"h1",
|
|
2527
|
+
"hero",
|
|
2528
|
+
"titulo"
|
|
2529
|
+
]
|
|
2530
|
+
},
|
|
2531
|
+
{
|
|
2532
|
+
"name": "SectionHeading",
|
|
2533
|
+
"import": "import { SectionHeading } from \"@fluencypassdevs/cycle/marketing/typography/section-heading\"",
|
|
2534
|
+
"description": "MARKETING — Camada 2a. Titulo de dobra (h2 default). Dois pesos: light (font-light elegante, default) e bold (font-bold impacto). leading 1.15, text-balance. Pareie com SectionEyebrow acima e SectionSubtitle abaixo.",
|
|
2535
|
+
"props": [
|
|
2536
|
+
{
|
|
2537
|
+
"name": "as",
|
|
2538
|
+
"type": "\"h2\" | \"h3\"",
|
|
2539
|
+
"default": "\"h2\""
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
"name": "weight",
|
|
2543
|
+
"type": "\"light\" | \"bold\"",
|
|
2544
|
+
"default": "\"light\""
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
"name": "align",
|
|
2548
|
+
"type": "\"left\" | \"center\"",
|
|
2549
|
+
"default": "\"center\""
|
|
2550
|
+
},
|
|
2551
|
+
{
|
|
2552
|
+
"name": "maxW",
|
|
2553
|
+
"type": "\"wide\" | \"prose\"",
|
|
2554
|
+
"default": "\"wide\"",
|
|
2555
|
+
"note": "wide=max-w-5xl, prose=max-w-3xl"
|
|
2556
|
+
}
|
|
2557
|
+
],
|
|
2558
|
+
"example": "<SectionHeading>\n Conteudo, professores e tecnologia no mesmo lugar\n</SectionHeading>\n\n<SectionHeading weight=\"bold\" align=\"left\" maxW=\"prose\">\n Mude o jeito de aprender ingles\n</SectionHeading>",
|
|
2559
|
+
"keywords": [
|
|
2560
|
+
"marketing",
|
|
2561
|
+
"landing",
|
|
2562
|
+
"typography",
|
|
2563
|
+
"heading",
|
|
2564
|
+
"h2",
|
|
2565
|
+
"section",
|
|
2566
|
+
"dobra"
|
|
2567
|
+
]
|
|
2568
|
+
},
|
|
2569
|
+
{
|
|
2570
|
+
"name": "SectionEyebrow",
|
|
2571
|
+
"import": "import { SectionEyebrow } from \"@fluencypassdevs/cycle/marketing/typography/section-eyebrow\"",
|
|
2572
|
+
"description": "MARKETING — Camada 2a. Rotulo monospace acima do SectionHeading que categoriza a dobra. text-xs font-mono uppercase tracking-widest text-muted-foreground.",
|
|
2573
|
+
"props": [
|
|
2574
|
+
{
|
|
2575
|
+
"name": "as",
|
|
2576
|
+
"type": "\"p\" | \"span\" | \"div\"",
|
|
2577
|
+
"default": "\"p\""
|
|
2578
|
+
},
|
|
2579
|
+
{
|
|
2580
|
+
"name": "align",
|
|
2581
|
+
"type": "\"left\" | \"center\"",
|
|
2582
|
+
"default": "\"left\""
|
|
2583
|
+
}
|
|
2584
|
+
],
|
|
2585
|
+
"example": "<SectionEyebrow align=\"center\">Para empresas</SectionEyebrow>\n<SectionHeading>Acelere o ingles do seu time</SectionHeading>",
|
|
2586
|
+
"keywords": [
|
|
2587
|
+
"marketing",
|
|
2588
|
+
"landing",
|
|
2589
|
+
"typography",
|
|
2590
|
+
"eyebrow",
|
|
2591
|
+
"label",
|
|
2592
|
+
"rotulo",
|
|
2593
|
+
"categoria"
|
|
2594
|
+
]
|
|
2595
|
+
},
|
|
2596
|
+
{
|
|
2597
|
+
"name": "SectionSubtitle",
|
|
2598
|
+
"import": "import { SectionSubtitle } from \"@fluencypassdevs/cycle/marketing/typography/section-subtitle\"",
|
|
2599
|
+
"description": "MARKETING — Camada 2a. Body de apoio abaixo do SectionHeading. text-base sm:text-lg md:text-xl muted-foreground leading-relaxed text-balance max-w-3xl. align center (default) adiciona mx-auto.",
|
|
2600
|
+
"props": [
|
|
2601
|
+
{
|
|
2602
|
+
"name": "align",
|
|
2603
|
+
"type": "\"left\" | \"center\"",
|
|
2604
|
+
"default": "\"center\""
|
|
2605
|
+
}
|
|
2606
|
+
],
|
|
2607
|
+
"example": "<SectionHeading>Nossa solucao em 3 passos</SectionHeading>\n<SectionSubtitle>\n Do diagnostico ao certificado, num caminho desenhado pra resultado.\n</SectionSubtitle>",
|
|
2608
|
+
"keywords": [
|
|
2609
|
+
"marketing",
|
|
2610
|
+
"landing",
|
|
2611
|
+
"typography",
|
|
2612
|
+
"subtitle",
|
|
2613
|
+
"subtitulo",
|
|
2614
|
+
"body",
|
|
2615
|
+
"lead"
|
|
2616
|
+
]
|
|
2617
|
+
},
|
|
2618
|
+
{
|
|
2619
|
+
"name": "CircleGlow",
|
|
2620
|
+
"import": "import { CircleGlow } from \"@fluencypassdevs/cycle/marketing/effects/circle-glow\"",
|
|
2621
|
+
"description": "MARKETING — Camada 2a. Decoracao de elipse radial pulsante (4.5s scale + opacity) posicionada absolute. Container precisa ser relative. Sempre aria-hidden + pointer-events none. Respeita prefers-reduced-motion.",
|
|
2622
|
+
"props": [
|
|
2623
|
+
{
|
|
2624
|
+
"name": "size",
|
|
2625
|
+
"type": "\"sm\" | \"md\" | \"lg\"",
|
|
2626
|
+
"default": "\"lg\"",
|
|
2627
|
+
"note": "controla transform: scale()"
|
|
2628
|
+
}
|
|
2629
|
+
],
|
|
2630
|
+
"example": "<div className=\"relative overflow-hidden\">\n <CircleGlow className=\"-z-10\" />\n <div className=\"grid grid-cols-3 gap-6\">{cards}</div>\n</div>",
|
|
2631
|
+
"keywords": [
|
|
2632
|
+
"marketing",
|
|
2633
|
+
"landing",
|
|
2634
|
+
"effects",
|
|
2635
|
+
"glow",
|
|
2636
|
+
"decoration",
|
|
2637
|
+
"background",
|
|
2638
|
+
"rose"
|
|
2639
|
+
]
|
|
2640
|
+
},
|
|
2641
|
+
{
|
|
2642
|
+
"name": "CardDarkGlow",
|
|
2643
|
+
"import": "import { CardDarkGlow } from \"@fluencypassdevs/cycle/marketing/effects/card-dark-glow\"",
|
|
2644
|
+
"description": "MARKETING — Camada 2a. Wrapper de card com inset highlight + glow rose subtil + hover lift opcional (translateY -3px). Prop interactive (default true) habilita o hover. Pareie com CircleGlow no container externo pro efeito 'dark premium'.",
|
|
2645
|
+
"props": [
|
|
2646
|
+
{
|
|
2647
|
+
"name": "as",
|
|
2648
|
+
"type": "\"div\" | \"article\" | \"section\"",
|
|
2649
|
+
"default": "\"div\""
|
|
2650
|
+
},
|
|
2651
|
+
{
|
|
2652
|
+
"name": "interactive",
|
|
2653
|
+
"type": "boolean",
|
|
2654
|
+
"default": "true",
|
|
2655
|
+
"note": "habilita hover lift + glow stronger"
|
|
2656
|
+
}
|
|
2657
|
+
],
|
|
2658
|
+
"example": "<CardDarkGlow className=\"rounded-2xl bg-card border p-6\">\n <h3>Titulo</h3>\n <p>Descricao do card</p>\n</CardDarkGlow>\n\n<CardDarkGlow interactive={false}>...sem hover</CardDarkGlow>",
|
|
2659
|
+
"keywords": [
|
|
2660
|
+
"marketing",
|
|
2661
|
+
"landing",
|
|
2662
|
+
"effects",
|
|
2663
|
+
"card",
|
|
2664
|
+
"shadow",
|
|
2665
|
+
"glow",
|
|
2666
|
+
"hover",
|
|
2667
|
+
"lift"
|
|
2668
|
+
]
|
|
2669
|
+
},
|
|
2670
|
+
{
|
|
2671
|
+
"name": "Marquee",
|
|
2672
|
+
"import": "import { Marquee } from \"@fluencypassdevs/cycle/marketing/effects/marquee\"",
|
|
2673
|
+
"description": "MARKETING — Camada 2a. Scroll horizontal infinito (logo cloud, partner band). Duplica children pra loop seamless (segundo bloco aria-hidden). Pausa em hover e focus-within (a11y). Respeita prefers-reduced-motion.",
|
|
2674
|
+
"props": [
|
|
2675
|
+
{
|
|
2676
|
+
"name": "speed",
|
|
2677
|
+
"type": "number",
|
|
2678
|
+
"default": "40",
|
|
2679
|
+
"note": "duracao de um ciclo em segundos"
|
|
2680
|
+
},
|
|
2681
|
+
{
|
|
2682
|
+
"name": "direction",
|
|
2683
|
+
"type": "\"left\" | \"right\"",
|
|
2684
|
+
"default": "\"left\""
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
"name": "pauseOnHover",
|
|
2688
|
+
"type": "boolean",
|
|
2689
|
+
"default": "true"
|
|
2690
|
+
},
|
|
2691
|
+
{
|
|
2692
|
+
"name": "gap",
|
|
2693
|
+
"type": "number",
|
|
2694
|
+
"default": "48",
|
|
2695
|
+
"note": "espacamento entre items em px"
|
|
2696
|
+
}
|
|
2697
|
+
],
|
|
2698
|
+
"example": "<Marquee speed={30} gap={64}>\n <img src=\"/logos/logo-a.png\" alt=\"Cliente A\" />\n <img src=\"/logos/logo-b.png\" alt=\"Cliente B\" />\n <img src=\"/logos/logo-c.png\" alt=\"Cliente C\" />\n</Marquee>",
|
|
2699
|
+
"keywords": [
|
|
2700
|
+
"marketing",
|
|
2701
|
+
"landing",
|
|
2702
|
+
"effects",
|
|
2703
|
+
"marquee",
|
|
2704
|
+
"scroll",
|
|
2705
|
+
"horizontal",
|
|
2706
|
+
"logo",
|
|
2707
|
+
"cloud",
|
|
2708
|
+
"partner",
|
|
2709
|
+
"band"
|
|
2710
|
+
]
|
|
2711
|
+
},
|
|
2712
|
+
{
|
|
2713
|
+
"name": "MagneticButton",
|
|
2714
|
+
"import": "import { MagneticButton } from \"@fluencypassdevs/cycle/marketing/effects/magnetic-button\"",
|
|
2715
|
+
"description": "MARKETING — Camada 2b. Wrapper que aplica efeito magnetico no filho (puxa em direcao ao cursor). Escreve transform direto no DOM via ref + RAF throttle. IntersectionObserver gating (rootMargin 200px). Drop-shadow rose via CSS vars --shadow-brand-glow-idle/-hover (consumer override). Skip total em prefers-reduced-motion e pointer:coarse (touch).",
|
|
2716
|
+
"props": [
|
|
2717
|
+
{
|
|
2718
|
+
"name": "strength",
|
|
2719
|
+
"type": "number",
|
|
2720
|
+
"default": "0.25",
|
|
2721
|
+
"note": "multiplicador do offset"
|
|
2722
|
+
},
|
|
2723
|
+
{
|
|
2724
|
+
"name": "radius",
|
|
2725
|
+
"type": "number",
|
|
2726
|
+
"default": "100",
|
|
2727
|
+
"note": "distancia em px na qual o efeito ativa"
|
|
2728
|
+
}
|
|
2729
|
+
],
|
|
2730
|
+
"example": "<MagneticButton>\n <a href=\"#vendas\">\n <Button variant=\"default\">Quero saber mais</Button>\n </a>\n</MagneticButton>\n\n<MagneticButton strength={0.4} radius={150}>\n <CustomElement />\n</MagneticButton>",
|
|
2731
|
+
"keywords": [
|
|
2732
|
+
"marketing",
|
|
2733
|
+
"landing",
|
|
2734
|
+
"effects",
|
|
2735
|
+
"magnetic",
|
|
2736
|
+
"hover",
|
|
2737
|
+
"cursor",
|
|
2738
|
+
"interactive",
|
|
2739
|
+
"premium"
|
|
2740
|
+
]
|
|
2741
|
+
},
|
|
2742
|
+
{
|
|
2743
|
+
"name": "RotatingWord",
|
|
2744
|
+
"import": "import { RotatingWord } from \"@fluencypassdevs/cycle/marketing/effects/rotating-word\"",
|
|
2745
|
+
"description": "MARKETING — Camada 2b. Typewriter de palavras em loop (typing → holding → erasing). Cor herda do parent via currentColor (consumer aplica text-[color]). aria-live polite + aria-atomic. Em prefers-reduced-motion, mostra so primeira palavra estatica sem cursor.",
|
|
2746
|
+
"props": [
|
|
2747
|
+
{
|
|
2748
|
+
"name": "words",
|
|
2749
|
+
"type": "string[]",
|
|
2750
|
+
"default": "-",
|
|
2751
|
+
"note": "obrigatorio, palavras a ciclar"
|
|
2752
|
+
},
|
|
2753
|
+
{
|
|
2754
|
+
"name": "typingMs",
|
|
2755
|
+
"type": "number",
|
|
2756
|
+
"default": "80",
|
|
2757
|
+
"note": "velocidade de digitacao ms/caractere"
|
|
2758
|
+
},
|
|
2759
|
+
{
|
|
2760
|
+
"name": "eraseMs",
|
|
2761
|
+
"type": "number",
|
|
2762
|
+
"default": "45",
|
|
2763
|
+
"note": "velocidade de apagar"
|
|
2764
|
+
},
|
|
2765
|
+
{
|
|
2766
|
+
"name": "holdMs",
|
|
2767
|
+
"type": "number",
|
|
2768
|
+
"default": "1500",
|
|
2769
|
+
"note": "tempo segurando a palavra completa"
|
|
2770
|
+
}
|
|
2771
|
+
],
|
|
2772
|
+
"example": "<h1>\n Aprenda ingles com{\" \"}\n <RotatingWord\n className=\"text-[color:var(--brand-default)]\"\n words={[\"IA\", \"proposito\", \"confianca\"]}\n />\n</h1>",
|
|
2773
|
+
"keywords": [
|
|
2774
|
+
"marketing",
|
|
2775
|
+
"landing",
|
|
2776
|
+
"effects",
|
|
2777
|
+
"typewriter",
|
|
2778
|
+
"rotating",
|
|
2779
|
+
"word",
|
|
2780
|
+
"hero",
|
|
2781
|
+
"typing"
|
|
2782
|
+
]
|
|
2783
|
+
},
|
|
2784
|
+
{
|
|
2785
|
+
"name": "HandUnderline",
|
|
2786
|
+
"import": "import { HandUnderline } from \"@fluencypassdevs/cycle/marketing/effects/hand-underline\"",
|
|
2787
|
+
"description": "MARKETING — Camada 2b. Wrapper que desenha SVG underline em curva sutil abaixo do texto, animada via stroke-dasharray quando entra no viewport (threshold 0.6). Cor herda do parent (stroke=currentColor). Em prefers-reduced-motion, desenha completo direto sem animar.",
|
|
2788
|
+
"props": [
|
|
2789
|
+
{
|
|
2790
|
+
"name": "delay",
|
|
2791
|
+
"type": "number",
|
|
2792
|
+
"default": "600",
|
|
2793
|
+
"note": "ms entre intersecao e inicio do draw"
|
|
2794
|
+
},
|
|
2795
|
+
{
|
|
2796
|
+
"name": "duration",
|
|
2797
|
+
"type": "number",
|
|
2798
|
+
"default": "780",
|
|
2799
|
+
"note": "duracao do draw em ms"
|
|
2800
|
+
}
|
|
2801
|
+
],
|
|
2802
|
+
"example": "<h2>\n Acelere o ingles do seu{\" \"}\n <HandUnderline className=\"text-[color:var(--brand-default)]\">\n time corporativo\n </HandUnderline>\n</h2>",
|
|
2803
|
+
"keywords": [
|
|
2804
|
+
"marketing",
|
|
2805
|
+
"landing",
|
|
2806
|
+
"effects",
|
|
2807
|
+
"underline",
|
|
2808
|
+
"highlight",
|
|
2809
|
+
"draw",
|
|
2810
|
+
"scroll-trigger"
|
|
2811
|
+
]
|
|
2812
|
+
},
|
|
2813
|
+
{
|
|
2814
|
+
"name": "CtaBrand",
|
|
2815
|
+
"import": "import { CtaBrand } from \"@fluencypassdevs/cycle/marketing/buttons/cta-brand\"",
|
|
2816
|
+
"description": "MARKETING — Camada 2b. CTA principal de marketing — gradient brand rose (from-brand-soft to-brand-dark) + rounded-full + drop-shadow glow + brightness hover + MagneticButton embutido (sempre). Sempre renderiza como <a> com href. Pra acoes de JS sem URL, use Button core.",
|
|
2817
|
+
"props": [
|
|
2818
|
+
{
|
|
2819
|
+
"name": "href",
|
|
2820
|
+
"type": "string",
|
|
2821
|
+
"default": "-",
|
|
2822
|
+
"note": "obrigatorio, sempre renderiza como <a>"
|
|
2823
|
+
},
|
|
2824
|
+
{
|
|
2825
|
+
"name": "external",
|
|
2826
|
+
"type": "boolean",
|
|
2827
|
+
"default": "false",
|
|
2828
|
+
"note": "target=_blank + rel noopener noreferrer"
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
"name": "size",
|
|
2832
|
+
"type": "\"md\" | \"lg\"",
|
|
2833
|
+
"default": "\"lg\"",
|
|
2834
|
+
"note": "md=h-11 px-7. lg=h-13 px-10"
|
|
2835
|
+
},
|
|
2836
|
+
{
|
|
2837
|
+
"name": "disableMagnetic",
|
|
2838
|
+
"type": "boolean",
|
|
2839
|
+
"default": "false",
|
|
2840
|
+
"note": "escape hatch raro (popups/drawers)"
|
|
2841
|
+
}
|
|
2842
|
+
],
|
|
2843
|
+
"example": "<CtaBrand href=\"#vendas\">\n Solicitar demonstracao\n</CtaBrand>\n\n<CtaBrand href=\"https://app.fluencypass.com\" external size=\"md\">\n Acessar app\n</CtaBrand>",
|
|
2844
|
+
"keywords": [
|
|
2845
|
+
"marketing",
|
|
2846
|
+
"landing",
|
|
2847
|
+
"buttons",
|
|
2848
|
+
"cta",
|
|
2849
|
+
"brand",
|
|
2850
|
+
"gradient",
|
|
2851
|
+
"magnetic",
|
|
2852
|
+
"hero",
|
|
2853
|
+
"conversao"
|
|
2854
|
+
]
|
|
2855
|
+
},
|
|
2856
|
+
{
|
|
2857
|
+
"name": "LinkBrand",
|
|
2858
|
+
"import": "import { LinkBrand } from \"@fluencypassdevs/cycle/marketing/buttons/link-brand\"",
|
|
2859
|
+
"description": "MARKETING — Camada 2b. Link de texto discreto da marca — text-brand-default com hover pra brand-dark, transition-colors, focus-visible outline. Sem underline por default (consumer adiciona hover:underline se quiser). Renderiza como <a> (default) ou <button> via prop as.",
|
|
2860
|
+
"props": [
|
|
2861
|
+
{
|
|
2862
|
+
"name": "as",
|
|
2863
|
+
"type": "\"a\" | \"button\"",
|
|
2864
|
+
"default": "\"a\""
|
|
2865
|
+
},
|
|
2866
|
+
{
|
|
2867
|
+
"name": "href",
|
|
2868
|
+
"type": "string",
|
|
2869
|
+
"default": "-",
|
|
2870
|
+
"note": "obrigatorio quando as=a"
|
|
2871
|
+
},
|
|
2872
|
+
{
|
|
2873
|
+
"name": "external",
|
|
2874
|
+
"type": "boolean",
|
|
2875
|
+
"default": "false"
|
|
2876
|
+
}
|
|
2877
|
+
],
|
|
2878
|
+
"example": "<LinkBrand href=\"/precos\">Ver planos</LinkBrand>\n\n<LinkBrand href=\"https://twitter.com\" external>\n Siga no Twitter\n</LinkBrand>\n\n<LinkBrand as=\"button\" onClick={() => openModal()}>\n Abrir filtros\n</LinkBrand>",
|
|
2879
|
+
"keywords": [
|
|
2880
|
+
"marketing",
|
|
2881
|
+
"landing",
|
|
2882
|
+
"buttons",
|
|
2883
|
+
"link",
|
|
2884
|
+
"brand",
|
|
2885
|
+
"nav",
|
|
2886
|
+
"footer",
|
|
2887
|
+
"inline"
|
|
2888
|
+
]
|
|
2889
|
+
},
|
|
2890
|
+
{
|
|
2891
|
+
"name": "FluencypassLogo",
|
|
2892
|
+
"import": "import { FluencypassLogo, FluencypassIcon } from \"@fluencypassdevs/cycle\"",
|
|
2893
|
+
"description": "Logo da Fluencypass (icone coral + texto). 5 sizes (xs, sm, md, lg, xl). FluencypassIcon para o icone sozinho.",
|
|
2894
|
+
"props": [
|
|
2895
|
+
{
|
|
2896
|
+
"name": "size",
|
|
2897
|
+
"type": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"",
|
|
2898
|
+
"default": "\"md\""
|
|
2899
|
+
}
|
|
2900
|
+
],
|
|
2901
|
+
"example": "<FluencypassLogo size=\"md\" />\n<FluencypassIcon className=\"h-7 w-auto\" />",
|
|
2902
|
+
"keywords": [
|
|
2903
|
+
"logo",
|
|
2904
|
+
"fluencypass",
|
|
2905
|
+
"marca",
|
|
2906
|
+
"brand",
|
|
2907
|
+
"icone"
|
|
2908
|
+
]
|
|
2909
|
+
},
|
|
2910
|
+
{
|
|
2911
|
+
"name": "ProductLogo",
|
|
2912
|
+
"import": "import { ProductLogo, ClassLogo, PrivateTalkLogo, GroupTalkLogo } from \"@fluencypassdevs/cycle\"",
|
|
2913
|
+
"description": "Logo de produto (icone Fluencypass coral + label). 5 sizes (xs=16px, sm=20px, md=24px, lg=28px, xl=32px). Pre-built: ClassLogo, PrivateTalkLogo, GroupTalkLogo.",
|
|
2914
|
+
"props": [
|
|
2915
|
+
{
|
|
2916
|
+
"name": "label",
|
|
2917
|
+
"type": "string",
|
|
2918
|
+
"default": "-"
|
|
2919
|
+
},
|
|
2920
|
+
{
|
|
2921
|
+
"name": "size",
|
|
2922
|
+
"type": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"",
|
|
2923
|
+
"default": "\"sm\""
|
|
2924
|
+
}
|
|
2925
|
+
],
|
|
2926
|
+
"example": "<ClassLogo size=\"md\" />\n<PrivateTalkLogo size=\"sm\" />\n<GroupTalkLogo size=\"lg\" />\n<ProductLogo label=\"Impulse\" size=\"md\" />",
|
|
2927
|
+
"keywords": [
|
|
2928
|
+
"logo",
|
|
2929
|
+
"produto",
|
|
2930
|
+
"class",
|
|
2931
|
+
"private",
|
|
2932
|
+
"group",
|
|
2933
|
+
"talk",
|
|
2934
|
+
"marca"
|
|
2935
|
+
]
|
|
2936
|
+
}
|
|
2937
|
+
]
|