@ranimontagna/agent-toolkit 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +8 -8
- package/dist/src/installers/superpowers.js +23 -7
- package/dist/src/installers/superpowers.js.map +1 -1
- package/package.json +5 -5
- package/skills/backend/fastify-best-practices/NOTICE.md +1 -1
- package/skills/backend/fastify-best-practices/rules/authentication.md +13 -0
- package/skills/backend/fastify-best-practices/rules/configuration.md +9 -0
- package/skills/backend/fastify-best-practices/rules/content-type.md +16 -0
- package/skills/backend/fastify-best-practices/rules/cors-security.md +18 -0
- package/skills/backend/fastify-best-practices/rules/database.md +12 -0
- package/skills/backend/fastify-best-practices/rules/decorators.md +14 -0
- package/skills/backend/fastify-best-practices/rules/deployment.md +16 -0
- package/skills/backend/fastify-best-practices/rules/error-handling.md +16 -0
- package/skills/backend/fastify-best-practices/rules/hooks.md +20 -0
- package/skills/backend/fastify-best-practices/rules/http-proxy.md +11 -0
- package/skills/backend/fastify-best-practices/rules/logging.md +18 -0
- package/skills/backend/fastify-best-practices/rules/performance.md +20 -0
- package/skills/backend/fastify-best-practices/rules/plugins.md +14 -0
- package/skills/backend/fastify-best-practices/rules/routes.md +18 -0
- package/skills/backend/fastify-best-practices/rules/schemas.md +20 -0
- package/skills/backend/fastify-best-practices/rules/serialization.md +19 -0
- package/skills/backend/fastify-best-practices/rules/testing.md +17 -0
- package/skills/backend/fastify-best-practices/rules/typescript.md +15 -0
- package/skills/backend/fastify-best-practices/rules/websockets.md +15 -0
- package/skills/backend/go/golang-patterns/NOTICE.md +1 -1
- package/skills/backend/go/golang-patterns/SKILL.md +2 -1
- package/skills/devops/docker-patterns/NOTICE.md +1 -1
- package/skills/devops/docker-patterns/SKILL.md +3 -3
- package/skills/frontend/design/revenue-centric-design/NOTICE.md +1 -1
- package/skills/frontend/design/revenue-centric-design/SKILL.md +6 -4
- package/skills/frontend/design/revenue-centric-design/assets/1985681720104903142__1.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/1999584679247134761__1.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/2000930776636940333__1.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/2018693884449009956__3.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/2081714430811730162__1.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/2092692547244007852__q__1.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/2092692547244007852__q__2.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/assets/2092692547244007852__q__3.jpg +0 -0
- package/skills/frontend/design/revenue-centric-design/references/checkout-and-forms.md +39 -0
- package/skills/frontend/design/revenue-centric-design/references/churn-and-retention.md +25 -0
- package/skills/frontend/design/revenue-centric-design/references/conversion-and-landing-pages.md +52 -1
- package/skills/frontend/design/revenue-centric-design/references/dashboards-and-data-viz.md +23 -0
- package/skills/frontend/design/revenue-centric-design/references/metrics-and-experimentation.md +13 -0
- package/skills/frontend/design/revenue-centric-design/references/onboarding-and-activation.md +7 -1
- package/skills/frontend/design/revenue-centric-design/references/pricing-and-monetization.md +35 -8
- package/skills/frontend/design/revenue-centric-design/references/product-strategy-and-features.md +37 -0
- package/skills/frontend/design/revenue-centric-design/references/revenue-centric-design.md +2 -2
- package/skills/frontend/design/ui-ux-pro-max/NOTICE.md +6 -4
- package/skills/frontend/design/ui-ux-pro-max/SKILL.md +103 -573
- package/skills/frontend/design/ui-ux-pro-max/data/app-interface.csv +29 -27
- package/skills/frontend/design/ui-ux-pro-max/data/catalog-summary.json +78 -0
- package/skills/frontend/design/ui-ux-pro-max/data/charts.csv +26 -26
- package/skills/frontend/design/ui-ux-pro-max/data/colors.csv +191 -160
- package/skills/frontend/design/ui-ux-pro-max/data/data-provenance.json +1348 -0
- package/skills/frontend/design/ui-ux-pro-max/data/google-font-licenses.json +20185 -0
- package/skills/frontend/design/ui-ux-pro-max/data/google-fonts.csv +1934 -1923
- package/skills/frontend/design/ui-ux-pro-max/data/icons.csv +106 -106
- package/skills/frontend/design/ui-ux-pro-max/data/landing.csv +35 -35
- package/skills/frontend/design/ui-ux-pro-max/data/motion.csv +18 -0
- package/skills/frontend/design/ui-ux-pro-max/data/phosphor-icons-upstream.json +32582 -0
- package/skills/frontend/design/ui-ux-pro-max/data/products.csv +192 -161
- package/skills/frontend/design/ui-ux-pro-max/data/react-performance.csv +37 -37
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/angular.csv +51 -51
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/astro.csv +54 -54
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/avalonia.csv +57 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/html-tailwind.csv +60 -56
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/javafx.csv +76 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/laravel.csv +51 -51
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nextjs.csv +62 -53
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxt-ui.csv +77 -51
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxtjs.csv +68 -59
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/react.csv +67 -54
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/shadcn.csv +69 -61
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/svelte.csv +56 -54
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/threejs.csv +54 -54
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/uno.csv +60 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/uwp.csv +56 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/vue.csv +50 -50
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/winui.csv +60 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/wpf.csv +57 -0
- package/skills/frontend/design/ui-ux-pro-max/data/styles.csv +89 -85
- package/skills/frontend/design/ui-ux-pro-max/data/typography.csv +74 -73
- package/skills/frontend/design/ui-ux-pro-max/data/ui-reasoning.csv +193 -162
- package/skills/frontend/design/ui-ux-pro-max/data/ux-guidelines.csv +30 -10
- package/skills/frontend/design/ui-ux-pro-max/references/pro-rules.md +117 -0
- package/skills/frontend/design/ui-ux-pro-max/references/quick-reference.md +256 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/core.py +800 -69
- package/skills/frontend/design/ui-ux-pro-max/scripts/design_system.py +700 -180
- package/skills/frontend/design/ui-ux-pro-max/scripts/reasoning_contract.py +123 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/search.py +105 -42
- package/skills/frontend/design/ui-ux-pro-max/scripts/validate_data.py +1095 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/NOTICE.md +1 -1
- package/skills/frontend/react-native/react-native-unistyles-v3/SKILL.md +33 -24
- package/skills/frontend/react-native/react-native-unistyles-v3/references/api-reference.md +135 -78
- package/skills/frontend/react-native/react-native-unistyles-v3/references/common-issues.md +48 -31
- package/skills/frontend/react-native/react-native-unistyles-v3/references/setup-guide.md +76 -34
- package/skills/frontend/react-native/react-native-unistyles-v3/references/styling-patterns.md +145 -52
- package/skills/frontend/react-native/react-native-unistyles-v3/references/third-party-integration.md +76 -27
- package/skills/media/brag-slim/NOTICE.md +3 -3
- package/skills/media/brag-slim/SKILL.md +4 -0
- package/tools.lock.json +20 -20
- package/skills/frontend/design/revenue-centric-design/assets/2018693884449009956__1.jpg +0 -0
- package/skills/frontend/design/ui-ux-pro-max/data/_sync_all.py +0 -414
- package/skills/frontend/design/ui-ux-pro-max/data/design.csv +0 -1776
- package/skills/frontend/design/ui-ux-pro-max/data/draft.csv +0 -1779
package/skills/frontend/react-native/react-native-unistyles-v3/references/styling-patterns.md
CHANGED
|
@@ -59,7 +59,7 @@ const styles = StyleSheet.create((theme, rt) => ({
|
|
|
59
59
|
|
|
60
60
|
## Dynamic Functions
|
|
61
61
|
|
|
62
|
-
Pass arguments to styles at the call site. Arguments must be serializable.
|
|
62
|
+
Pass arguments to styles at the call site. Arguments must be serializable: Unistyles stores them in C++ and re-runs the function natively (theme/runtime changes, frozen screens re-linking). Functions are dropped and `Date`/`Map`/`Set`/class instances become plain objects — pass primitives or plain objects instead (e.g. `date.getTime()`).
|
|
63
63
|
|
|
64
64
|
```tsx
|
|
65
65
|
const styles = StyleSheet.create(theme => ({
|
|
@@ -128,9 +128,9 @@ const styles = StyleSheet.create(theme => ({
|
|
|
128
128
|
}))
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
### Nested breakpoints (transform, shadowOffset)
|
|
131
|
+
### Nested breakpoints (transform, shadowOffset, filter)
|
|
132
132
|
|
|
133
|
-
For properties expecting objects (like `transform` or `
|
|
133
|
+
For properties expecting objects (like `transform`, `shadowOffset` or `filter`), use breakpoints at the nested level:
|
|
134
134
|
|
|
135
135
|
```tsx
|
|
136
136
|
const styles = StyleSheet.create({
|
|
@@ -149,7 +149,7 @@ const styles = StyleSheet.create({
|
|
|
149
149
|
|
|
150
150
|
### Built-in breakpoints: landscape / portrait
|
|
151
151
|
|
|
152
|
-
Unistyles has built-in `landscape` and `portrait` breakpoints:
|
|
152
|
+
Unistyles has built-in `landscape` (width > height) and `portrait` (height >= width) breakpoints. On iOS/Android they're only available when you **haven't registered your own breakpoints**; on web they always become `@media (orientation: ...)` queries:
|
|
153
153
|
|
|
154
154
|
```tsx
|
|
155
155
|
const styles = StyleSheet.create({
|
|
@@ -241,6 +241,27 @@ const styles = StyleSheet.create(theme => ({
|
|
|
241
241
|
styles.useVariants({})
|
|
242
242
|
```
|
|
243
243
|
|
|
244
|
+
- Always pass an object — `useVariants(undefined)` throws on native.
|
|
245
|
+
- `undefined` and `null` values fall back to `default`; boolean `false` is NOT `default`.
|
|
246
|
+
- Without any `useVariants` call, variants (including `default`) are ignored.
|
|
247
|
+
|
|
248
|
+
### Numeric variant keys
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
const styles = StyleSheet.create({
|
|
252
|
+
heading: {
|
|
253
|
+
variants: {
|
|
254
|
+
level: {
|
|
255
|
+
1: { fontSize: 32 },
|
|
256
|
+
2: { fontSize: 24 },
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
styles.useVariants({ level: 1 }) // use whole numbers (converted to integers on native)
|
|
263
|
+
```
|
|
264
|
+
|
|
244
265
|
### Compound variants
|
|
245
266
|
|
|
246
267
|
Apply styles only when multiple variant values match simultaneously:
|
|
@@ -285,6 +306,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
285
306
|
|
|
286
307
|
type ChipVariants = UnistylesVariants<typeof styles>
|
|
287
308
|
// { size?: 'sm' | 'md' | 'lg'; color?: 'primary' | 'secondary' }
|
|
309
|
+
// Options of a group are merged across all styles — no need to repeat empty variants
|
|
288
310
|
|
|
289
311
|
type ChipProps = { label: string } & ChipVariants
|
|
290
312
|
|
|
@@ -306,26 +328,28 @@ import { mq, StyleSheet } from 'react-native-unistyles'
|
|
|
306
328
|
const styles = StyleSheet.create({
|
|
307
329
|
container: {
|
|
308
330
|
padding: {
|
|
309
|
-
[mq.only.width(null,
|
|
310
|
-
[mq.only.width(576,
|
|
311
|
-
[mq.only.width(768)]: 24, // width
|
|
331
|
+
[mq.only.width(null, 575)]: 8, // 0 <= width <= 575
|
|
332
|
+
[mq.only.width(576, 767)]: 16, // 576 <= width <= 767
|
|
333
|
+
[mq.only.width(768)]: 24, // width >= 768
|
|
312
334
|
},
|
|
313
335
|
},
|
|
314
336
|
sidebar: {
|
|
315
337
|
display: {
|
|
316
|
-
[mq.only.width(null,
|
|
338
|
+
[mq.only.width(null, 767)]: 'none',
|
|
317
339
|
[mq.only.width(768)]: 'flex',
|
|
318
340
|
},
|
|
319
341
|
},
|
|
320
342
|
})
|
|
321
343
|
```
|
|
322
344
|
|
|
323
|
-
|
|
345
|
+
**Both bounds are inclusive** — `mq.only.width(576, 768)` and `mq.only.width(768)` overlap at exactly 768 (on native the first matching query wins). `mq` has priority over breakpoint keys in the same object. Breakpoint names are resolved when `mq` is called, so `StyleSheet.configure` must run first.
|
|
346
|
+
|
|
347
|
+
### Mixing breakpoint names and numeric values
|
|
324
348
|
|
|
325
349
|
```tsx
|
|
326
|
-
mq.only.width('sm', 'lg') //
|
|
327
|
-
mq.only.width(320, 768) //
|
|
328
|
-
mq.only.height(400) // height
|
|
350
|
+
mq.only.width('sm', 'lg') // sm <= width <= lg
|
|
351
|
+
mq.only.width(320, 768) // 320 <= width <= 768 (same units as rt.screen)
|
|
352
|
+
mq.only.height(400) // height >= 400
|
|
329
353
|
```
|
|
330
354
|
|
|
331
355
|
### Combined width + height
|
|
@@ -334,7 +358,7 @@ mq.only.height(400) // height > 400px
|
|
|
334
358
|
const styles = StyleSheet.create({
|
|
335
359
|
panel: {
|
|
336
360
|
flexDirection: {
|
|
337
|
-
[mq.width(null,
|
|
361
|
+
[mq.width(null, 767).and.height(null, 499)]: 'column', // small screen
|
|
338
362
|
[mq.width(768).and.height(500)]: 'row', // large screen
|
|
339
363
|
},
|
|
340
364
|
},
|
|
@@ -408,6 +432,11 @@ Requires themes named exactly `light` and `dark`.
|
|
|
408
432
|
```tsx
|
|
409
433
|
import { UnistylesRuntime } from 'react-native-unistyles'
|
|
410
434
|
|
|
435
|
+
// setTheme throws while adaptive themes are enabled — disable them first
|
|
436
|
+
if (UnistylesRuntime.hasAdaptiveThemes) {
|
|
437
|
+
UnistylesRuntime.setAdaptiveThemes(false)
|
|
438
|
+
}
|
|
439
|
+
|
|
411
440
|
// Switch to specific theme
|
|
412
441
|
UnistylesRuntime.setTheme('dark')
|
|
413
442
|
|
|
@@ -439,7 +468,7 @@ import { ScopedTheme } from 'react-native-unistyles'
|
|
|
439
468
|
<DarkFooter />
|
|
440
469
|
</ScopedTheme>
|
|
441
470
|
|
|
442
|
-
// Invert: light→dark, dark→light
|
|
471
|
+
// Invert: light→dark, dark→light (no-op unless adaptiveThemes is enabled)
|
|
443
472
|
<ScopedTheme invertedAdaptive>
|
|
444
473
|
<InvertedSection />
|
|
445
474
|
</ScopedTheme>
|
|
@@ -461,7 +490,7 @@ const Layout = () => (
|
|
|
461
490
|
|
|
462
491
|
<MainContent />
|
|
463
492
|
|
|
464
|
-
{/* Hide mobile nav on tablet+ */}
|
|
493
|
+
{/* Hide mobile nav on tablet+ (width >= 768) */}
|
|
465
494
|
<Hide mq={mq.only.width(768)}>
|
|
466
495
|
<BottomNav />
|
|
467
496
|
</Hide>
|
|
@@ -490,7 +519,24 @@ const styles = StyleSheet.create(theme => ({
|
|
|
490
519
|
}))
|
|
491
520
|
```
|
|
492
521
|
|
|
493
|
-
|
|
522
|
+
`_web` can contain breakpoints and pseudo selectors but **not** `variants`; put a `_web` block inside a variant instead:
|
|
523
|
+
|
|
524
|
+
```tsx
|
|
525
|
+
const styles = StyleSheet.create({
|
|
526
|
+
grid: {
|
|
527
|
+
_web: { display: { xs: 'flex', md: 'grid' } }, // breakpoints OK
|
|
528
|
+
variants: {
|
|
529
|
+
size: {
|
|
530
|
+
large: { _web: { gridTemplateColumns: 'repeat(3, 1fr)' } }, // _web inside a variant OK
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
})
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Inside `_web` use plain CSS values (e.g. `transform: 'translateX(10px)'`), not RN-specific syntax.
|
|
538
|
+
|
|
539
|
+
### Pseudo-classes and pseudo-elements
|
|
494
540
|
|
|
495
541
|
```tsx
|
|
496
542
|
const styles = StyleSheet.create(theme => ({
|
|
@@ -502,7 +548,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
502
548
|
},
|
|
503
549
|
_active: {
|
|
504
550
|
backgroundColor: theme.colors.primaryActive,
|
|
505
|
-
transform:
|
|
551
|
+
transform: 'scale(0.98)', // CSS string inside _web
|
|
506
552
|
},
|
|
507
553
|
_focus: {
|
|
508
554
|
outlineWidth: 2,
|
|
@@ -512,18 +558,21 @@ const styles = StyleSheet.create(theme => ({
|
|
|
512
558
|
opacity: 0.5,
|
|
513
559
|
cursor: 'not-allowed',
|
|
514
560
|
},
|
|
515
|
-
|
|
561
|
+
'_focus-visible': {
|
|
516
562
|
outlineStyle: 'dashed',
|
|
517
563
|
},
|
|
518
|
-
|
|
564
|
+
'_focus-within': {
|
|
519
565
|
borderColor: theme.colors.focus,
|
|
520
566
|
},
|
|
567
|
+
_before: {
|
|
568
|
+
content: '"*"',
|
|
569
|
+
},
|
|
521
570
|
},
|
|
522
571
|
},
|
|
523
572
|
}))
|
|
524
573
|
```
|
|
525
574
|
|
|
526
|
-
|
|
575
|
+
Any standard (non-experimental) CSS pseudo-class / pseudo-element works, including functional ones like `_nth-child(2n)`: replace `:` / `::` with `_` and keep the CSS (kebab-case) name — `_hover`, `_active`, `'_focus-visible'`, `'_first-child'`, `_before`, `_after`, `_placeholder`, etc.
|
|
527
576
|
|
|
528
577
|
### Custom CSS class names
|
|
529
578
|
|
|
@@ -531,20 +580,28 @@ Supported pseudo-classes: `_hover`, `_active`, `_focus`, `_disabled`, `_focusVis
|
|
|
531
580
|
const styles = StyleSheet.create({
|
|
532
581
|
container: {
|
|
533
582
|
_web: {
|
|
534
|
-
_classNames: ['my-custom-class', 'another-class'],
|
|
583
|
+
_classNames: ['my-custom-class', 'another-class'], // or a single string
|
|
535
584
|
},
|
|
536
585
|
},
|
|
537
586
|
})
|
|
538
587
|
```
|
|
539
588
|
|
|
589
|
+
### CSS variables
|
|
590
|
+
|
|
591
|
+
With `CSSVars: true` (the default), theme strings become CSS variables (`--colors-primary`) under `:root.<themeName>` (or `prefers-color-scheme` media queries with adaptive themes), so switching themes only swaps the `html` class. Set `CSSVars: false` if your themes differ in non-string values (numbers, functions).
|
|
592
|
+
|
|
593
|
+
### RTL / logical props on web
|
|
594
|
+
|
|
595
|
+
RN logical props map to CSS logical properties and follow the document `dir`: `start`/`end` → `inset-inline-*`, `marginStart`/`marginEnd` → `margin-inline-*`, `paddingStart`/`paddingEnd` → `padding-inline-*`, `borderStart*`/`borderEnd*` color & width → `border-inline-*`. Corner radii (`borderTopStartRadius`, ...) still map to physical corners.
|
|
596
|
+
|
|
540
597
|
### getWebProps for custom web components
|
|
541
598
|
|
|
542
599
|
```tsx
|
|
543
|
-
import { getWebProps } from 'react-native-unistyles/web
|
|
600
|
+
import { getWebProps } from 'react-native-unistyles/web'
|
|
544
601
|
|
|
545
602
|
const CustomWebComponent = () => {
|
|
546
|
-
const
|
|
547
|
-
return <div
|
|
603
|
+
const webProps = getWebProps(styles.container) // { className, ref }
|
|
604
|
+
return <div {...webProps}>Content</div>
|
|
548
605
|
}
|
|
549
606
|
```
|
|
550
607
|
|
|
@@ -552,7 +609,7 @@ const CustomWebComponent = () => {
|
|
|
552
609
|
|
|
553
610
|
## Reanimated Integration
|
|
554
611
|
|
|
555
|
-
### useAnimatedTheme — access theme in worklets
|
|
612
|
+
### useAnimatedTheme — access theme in worklets (no re-renders, respects ScopedTheme)
|
|
556
613
|
|
|
557
614
|
```tsx
|
|
558
615
|
import { useAnimatedTheme } from 'react-native-unistyles/reanimated'
|
|
@@ -588,9 +645,13 @@ const styles = StyleSheet.create(theme => ({
|
|
|
588
645
|
|
|
589
646
|
const AnimatedButton = ({ isActive }) => {
|
|
590
647
|
styles.useVariants({ state: isActive ? 'active' : 'inactive' })
|
|
591
|
-
|
|
648
|
+
// SharedValue<string> holding the current variant color (also follows theme/breakpoint changes)
|
|
649
|
+
const color = useAnimatedVariantColor(styles.button, 'backgroundColor')
|
|
650
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
651
|
+
backgroundColor: withTiming(color.value, { duration: 300 }),
|
|
652
|
+
}))
|
|
592
653
|
|
|
593
|
-
return <Animated.View style={[styles.button,
|
|
654
|
+
return <Animated.View style={[styles.button, animatedStyle]} />
|
|
594
655
|
}
|
|
595
656
|
```
|
|
596
657
|
|
|
@@ -614,50 +675,74 @@ Never spread:
|
|
|
614
675
|
### App Router
|
|
615
676
|
|
|
616
677
|
```tsx
|
|
678
|
+
// Style.tsx
|
|
679
|
+
'use client'
|
|
680
|
+
|
|
681
|
+
import { PropsWithChildren, useRef } from 'react'
|
|
682
|
+
import { useServerUnistyles } from 'react-native-unistyles/server'
|
|
683
|
+
import { useServerInsertedHTML } from 'next/navigation'
|
|
684
|
+
import './unistyles'
|
|
685
|
+
|
|
686
|
+
export const Style = ({ children }: PropsWithChildren) => {
|
|
687
|
+
const isServerInserted = useRef(false)
|
|
688
|
+
const unistyles = useServerUnistyles() // also hydrates automatically on the client
|
|
689
|
+
|
|
690
|
+
useServerInsertedHTML(() => {
|
|
691
|
+
if (isServerInserted.current) {
|
|
692
|
+
return null
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
isServerInserted.current = true
|
|
696
|
+
|
|
697
|
+
return unistyles
|
|
698
|
+
})
|
|
699
|
+
|
|
700
|
+
return <>{children}</>
|
|
701
|
+
}
|
|
702
|
+
|
|
617
703
|
// app/layout.tsx
|
|
618
|
-
import
|
|
704
|
+
import '../unistyles'
|
|
705
|
+
import { Style } from '../Style'
|
|
619
706
|
|
|
620
707
|
export default function RootLayout({ children }) {
|
|
621
|
-
const styles = useServerUnistyles()
|
|
622
|
-
|
|
623
708
|
return (
|
|
624
|
-
<html>
|
|
625
|
-
<
|
|
626
|
-
|
|
709
|
+
<html lang="en">
|
|
710
|
+
<body>
|
|
711
|
+
<Style>{children}</Style>
|
|
712
|
+
</body>
|
|
627
713
|
</html>
|
|
628
714
|
)
|
|
629
715
|
}
|
|
630
|
-
|
|
631
|
-
// app/page.tsx (client component)
|
|
632
|
-
'use client'
|
|
633
|
-
import { hydrateServerUnistyles } from 'react-native-unistyles'
|
|
634
|
-
|
|
635
|
-
hydrateServerUnistyles()
|
|
636
716
|
```
|
|
637
717
|
|
|
638
718
|
### Pages Router
|
|
639
719
|
|
|
640
720
|
```tsx
|
|
641
721
|
// pages/_document.tsx
|
|
642
|
-
import { getServerUnistyles, resetServerUnistyles } from 'react-native-unistyles'
|
|
722
|
+
import { getServerUnistyles, resetServerUnistyles } from 'react-native-unistyles/server'
|
|
643
723
|
|
|
644
|
-
export default
|
|
645
|
-
|
|
724
|
+
export default class Document extends NextDocument {
|
|
725
|
+
static async getInitialProps({ renderPage }: DocumentContext) {
|
|
726
|
+
const page = await renderPage()
|
|
727
|
+
const styles = getServerUnistyles()
|
|
646
728
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
)
|
|
729
|
+
resetServerUnistyles() // required after every request
|
|
730
|
+
|
|
731
|
+
return { ...page, styles }
|
|
732
|
+
}
|
|
733
|
+
// render() ...
|
|
653
734
|
}
|
|
654
735
|
|
|
655
736
|
// pages/_app.tsx
|
|
656
|
-
import { hydrateServerUnistyles } from 'react-native-unistyles'
|
|
737
|
+
import { hydrateServerUnistyles } from 'react-native-unistyles/server'
|
|
657
738
|
|
|
658
|
-
|
|
739
|
+
useEffect(() => {
|
|
740
|
+
hydrateServerUnistyles()
|
|
741
|
+
}, [])
|
|
659
742
|
```
|
|
660
743
|
|
|
744
|
+
Without adaptive themes, Unistyles adds the theme class to `<html>` — add `suppressHydrationWarning` (or the class itself) to avoid a hydration warning.
|
|
745
|
+
|
|
661
746
|
---
|
|
662
747
|
|
|
663
748
|
## Runtime Values in Styles
|
|
@@ -687,14 +772,16 @@ const styles = StyleSheet.create((theme, rt) => ({
|
|
|
687
772
|
padding: rt.pixelRatio > 2 ? 16 : 12,
|
|
688
773
|
},
|
|
689
774
|
rtlAware: {
|
|
690
|
-
textAlign: rt.rtl ? 'right' : 'left',
|
|
775
|
+
textAlign: rt.rtl ? 'right' : 'left', // rtl updates live on Android/web; iOS needs a restart
|
|
691
776
|
},
|
|
692
777
|
}))
|
|
693
778
|
```
|
|
694
779
|
|
|
780
|
+
On web: `insets`, `statusBar` and `navigationBar` are `0`, `fontScale` is `1`, `pixelRatio` is `window.devicePixelRatio`.
|
|
781
|
+
|
|
695
782
|
### IME / Keyboard inset
|
|
696
783
|
|
|
697
|
-
`rt.insets.ime` provides the keyboard
|
|
784
|
+
`rt.insets.ime` provides the keyboard inset, replacing `react-native-reanimated`'s `useAnimatedKeyboard`:
|
|
698
785
|
|
|
699
786
|
```tsx
|
|
700
787
|
const styles = StyleSheet.create((theme, rt) => ({
|
|
@@ -703,3 +790,9 @@ const styles = StyleSheet.create((theme, rt) => ({
|
|
|
703
790
|
},
|
|
704
791
|
}))
|
|
705
792
|
```
|
|
793
|
+
|
|
794
|
+
- **iOS**: full keyboard height, animated frame by frame
|
|
795
|
+
- **Android**: keyboard height minus the bottom inset; animated on Android 11+ (API 30), jumps on older versions
|
|
796
|
+
- **Web**: always `0`
|
|
797
|
+
|
|
798
|
+
Read `ime` in `StyleSheet` (zero re-renders). Reading it in `useUnistyles`/`withUnistyles` subscribes only to `Ime` but re-renders on every animation frame.
|
package/skills/frontend/react-native/react-native-unistyles-v3/references/third-party-integration.md
CHANGED
|
@@ -4,7 +4,9 @@ How to integrate Unistyles v3 with third-party libraries, custom components, and
|
|
|
4
4
|
|
|
5
5
|
## withUnistyles HOC
|
|
6
6
|
|
|
7
|
-
For
|
|
7
|
+
For components that need theme-derived **non-style props** (e.g., `color`, `size`, `trackColor` — including RN components like `Button`/`Switch`), for `contentContainerStyle`, and for third-party views that don't expose a native ref (so Unistyles can't update them from C++).
|
|
8
|
+
|
|
9
|
+
On iOS/Android a wrapped component is always subscribed to theme changes; other dependencies (insets, breakpoints, ...) re-render it only if the mappings or the passed styles use them.
|
|
8
10
|
|
|
9
11
|
### Basic wrapping
|
|
10
12
|
|
|
@@ -22,7 +24,7 @@ const UniButton = withUnistyles(Button, (theme, rt) => ({
|
|
|
22
24
|
<UniButton title="Override" color="red" /> // overrides mapped color
|
|
23
25
|
```
|
|
24
26
|
|
|
25
|
-
###
|
|
27
|
+
### Mappings vs uniProps
|
|
26
28
|
|
|
27
29
|
The second argument to `withUnistyles` maps theme/runtime values to props. These are applied as **defaults** — the consumer can override them:
|
|
28
30
|
|
|
@@ -39,6 +41,31 @@ const UniIcon = withUnistyles(Icon, (theme) => ({
|
|
|
39
41
|
<UniIcon name="home" color="red" />
|
|
40
42
|
```
|
|
41
43
|
|
|
44
|
+
Mappings can't see component props/state. For that, pass `uniProps` per instance:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
const UniSwitch = withUnistyles(Switch)
|
|
48
|
+
|
|
49
|
+
<UniSwitch
|
|
50
|
+
uniProps={(theme) => ({
|
|
51
|
+
trackColor: { true: isDisabled ? theme.colors.disabled : theme.colors.primary },
|
|
52
|
+
})}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Priority: mappings < `uniProps` < inline props.
|
|
57
|
+
|
|
58
|
+
### Remounting with `key`
|
|
59
|
+
|
|
60
|
+
Mappings and `uniProps` can return `key` — it's used as the React `key` (not passed down), so changing it remounts the component (`uniProps` wins if both set):
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
const UniFlashList = withUnistyles(FlashList, (theme, rt) => ({
|
|
64
|
+
key: rt.isLandscape ? 'landscape' : 'portrait',
|
|
65
|
+
numColumns: rt.isLandscape ? 4 : 2,
|
|
66
|
+
}))
|
|
67
|
+
```
|
|
68
|
+
|
|
42
69
|
### Ref forwarding
|
|
43
70
|
|
|
44
71
|
Refs are forwarded automatically:
|
|
@@ -55,7 +82,7 @@ const inputRef = useRef<TextInput>(null)
|
|
|
55
82
|
|
|
56
83
|
### style and contentContainerStyle auto-processing
|
|
57
84
|
|
|
58
|
-
`withUnistyles` automatically processes `style` and `contentContainerStyle` props. You can pass Unistyles styles directly:
|
|
85
|
+
`withUnistyles` automatically processes `style` and `contentContainerStyle` props (they can't be returned from mappings/`uniProps`). You can pass Unistyles styles directly:
|
|
59
86
|
|
|
60
87
|
```tsx
|
|
61
88
|
const UniScrollView = withUnistyles(ScrollView)
|
|
@@ -70,7 +97,7 @@ const UniScrollView = withUnistyles(ScrollView)
|
|
|
70
97
|
|
|
71
98
|
## Babel Plugin: autoProcessPaths
|
|
72
99
|
|
|
73
|
-
|
|
100
|
+
The plugin processes every file under `root` and always ignores `node_modules`. `autoProcessPaths` opts 3rd party code in: inside these paths, `react-native` imports are replaced with Unistyles ref-borrowing factories, so the library's views update from C++:
|
|
74
101
|
|
|
75
102
|
```js
|
|
76
103
|
// babel.config.js
|
|
@@ -79,21 +106,21 @@ module.exports = {
|
|
|
79
106
|
['react-native-unistyles/plugin', {
|
|
80
107
|
root: 'src',
|
|
81
108
|
autoProcessPaths: [
|
|
82
|
-
'
|
|
83
|
-
'
|
|
109
|
+
'external-library/components',
|
|
110
|
+
'my-ui-kit/src',
|
|
84
111
|
],
|
|
85
112
|
}]
|
|
86
113
|
]
|
|
87
114
|
}
|
|
88
115
|
```
|
|
89
116
|
|
|
90
|
-
**Important:**
|
|
117
|
+
**Important:** each entry is matched as a **substring of the absolute file path** — use path fragments like `'some-lib/src'`, not relative paths like `'../packages/ui'` (those never match). `react-native-reanimated/src/component` and `react-native-reanimated/lib/module/component` are always included; your paths are added to them.
|
|
91
118
|
|
|
92
119
|
---
|
|
93
120
|
|
|
94
121
|
## Babel Plugin: autoProcessImports
|
|
95
122
|
|
|
96
|
-
|
|
123
|
+
Force-process any file (outside `node_modules`) that imports one of these sources — the way to cover monorepo packages that live outside `root`:
|
|
97
124
|
|
|
98
125
|
```js
|
|
99
126
|
// babel.config.js
|
|
@@ -101,19 +128,19 @@ module.exports = {
|
|
|
101
128
|
plugins: [
|
|
102
129
|
['react-native-unistyles/plugin', {
|
|
103
130
|
root: 'src',
|
|
104
|
-
autoProcessImports: ['@
|
|
131
|
+
autoProcessImports: ['@my-org/styles', '@my-org/ui'],
|
|
105
132
|
}]
|
|
106
133
|
]
|
|
107
134
|
}
|
|
108
135
|
```
|
|
109
136
|
|
|
110
|
-
This tells the plugin: "If a file imports
|
|
137
|
+
This tells the plugin: "If a file imports exactly `@my-org/styles`, process it like a file under `root`" (stylesheets + react-native component factories).
|
|
111
138
|
|
|
112
139
|
---
|
|
113
140
|
|
|
114
141
|
## Babel Plugin: autoRemapImports
|
|
115
142
|
|
|
116
|
-
|
|
143
|
+
Advanced (rarely needed): for a `node_modules` library that doesn't import `react-native` components directly (e.g. imports raw native components from `react-native/Libraries/...`), remap those imports to Unistyles factories (names from `react-native-unistyles/components/native`, e.g. `NativeView`, `NativeText`):
|
|
117
144
|
|
|
118
145
|
```js
|
|
119
146
|
// babel.config.js
|
|
@@ -121,21 +148,37 @@ module.exports = {
|
|
|
121
148
|
plugins: [
|
|
122
149
|
['react-native-unistyles/plugin', {
|
|
123
150
|
root: 'src',
|
|
124
|
-
autoRemapImports:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
151
|
+
autoRemapImports: [
|
|
152
|
+
{
|
|
153
|
+
path: 'node_modules/custom-library/components', // must be a path within node_modules
|
|
154
|
+
imports: [
|
|
155
|
+
{
|
|
156
|
+
isDefault: false,
|
|
157
|
+
name: 'NativeText',
|
|
158
|
+
path: 'react-native/Libraries/Text/TextNativeComponent',
|
|
159
|
+
mapTo: 'NativeText',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
isDefault: true,
|
|
163
|
+
path: 'react-native/Libraries/Components/View/ViewNativeComponent',
|
|
164
|
+
mapTo: 'NativeView',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
132
167
|
},
|
|
133
|
-
|
|
168
|
+
],
|
|
134
169
|
}]
|
|
135
170
|
]
|
|
136
171
|
}
|
|
137
172
|
```
|
|
138
173
|
|
|
174
|
+
It doesn't make non-RN views (e.g. SVG, icon fonts) reactive — use `withUnistyles` for those.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Re.Pack
|
|
179
|
+
|
|
180
|
+
Use `RepackUnistylePlugin` from `react-native-unistyles/repack-plugin` in your Rspack config instead of the Babel config entry; pass the same options as `unistylesPluginOptions` (`root` required). See [setup-guide.md](setup-guide.md#repack).
|
|
181
|
+
|
|
139
182
|
---
|
|
140
183
|
|
|
141
184
|
## React Compiler
|
|
@@ -168,6 +211,10 @@ module.exports = {
|
|
|
168
211
|
|
|
169
212
|
- `react-native-reanimated` 3.17.3+ **or** 4.0.0-beta.3+
|
|
170
213
|
|
|
214
|
+
### Theme in worklets
|
|
215
|
+
|
|
216
|
+
Use `useAnimatedTheme()` from `react-native-unistyles/reanimated` (a `SharedValue`, no re-renders, follows `ScopedTheme`) instead of `UnistylesRuntime.getTheme()` (doesn't update worklets) or `useUnistyles()` (re-renders). Animate variant colors with `useAnimatedVariantColor(styles.x, 'backgroundColor')`, which returns a `SharedValue<string>` to use inside `useAnimatedStyle`.
|
|
217
|
+
|
|
171
218
|
### CSS transitions workaround
|
|
172
219
|
|
|
173
220
|
When using Reanimated's CSS transitions, theme-dependent colors may become stale after theme changes. Force re-mount with `key`:
|
|
@@ -202,13 +249,9 @@ const animatedStyle = useAnimatedStyle(() => ({
|
|
|
202
249
|
|
|
203
250
|
---
|
|
204
251
|
|
|
205
|
-
##
|
|
206
|
-
|
|
207
|
-
Required for Android to get proper inset values. Install and use `rt.insets` in styles:
|
|
252
|
+
## Edge-to-edge (Android)
|
|
208
253
|
|
|
209
|
-
|
|
210
|
-
npm install react-native-edge-to-edge
|
|
211
|
-
```
|
|
254
|
+
Unistyles reads insets with `WindowInsetsCompat`, which needs an edge-to-edge layout — Unistyles enables it automatically. `react-native-edge-to-edge` is **optional** since v3.1.0; instead set `edgeToEdgeEnabled=true` in `android/gradle.properties` (Expo SDK 54+ does this for you). Keep `react-native-edge-to-edge` only if other libraries detect it (e.g. `react-native-bootsplash`, `react-native-permissions`). Then use `rt.insets` in styles:
|
|
212
255
|
|
|
213
256
|
```tsx
|
|
214
257
|
const styles = StyleSheet.create((theme, rt) => ({
|
|
@@ -225,6 +268,12 @@ This replaces `react-native-safe-area-context` for most use cases. No `<SafeArea
|
|
|
225
268
|
|
|
226
269
|
---
|
|
227
270
|
|
|
271
|
+
## Frozen / hidden screens
|
|
272
|
+
|
|
273
|
+
Screens hidden without unmounting keep their Unistyles bindings: `freezeOnBlur` (react-navigation / react-native-screens, via `react-freeze`), react-navigation `inactiveBehavior` (React `<Activity />`), and `Suspense` fallbacks. Theme/runtime changes made while hidden are applied when the screen becomes visible (Suspense/react-freeze since 3.2.0, `<Activity />` since 3.3.0, stale-style fixes in **3.4.0** — upgrade if frozen screens come back with outdated styles). Components using `useUnistyles`/`withUnistyles` re-render only after unfreezing.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
228
277
|
## FlatList Alternatives
|
|
229
278
|
|
|
230
279
|
`FlatList` has a known crash on orientation change ([#803](https://github.com/jpudysz/react-native-unistyles/issues/803)) — this is a React Native core issue, not Unistyles-specific.
|
|
@@ -273,7 +322,7 @@ For design system libraries (Paper, Tamagui, NativeBase, etc.) that have their o
|
|
|
273
322
|
Keep the library's theme in sync with Unistyles:
|
|
274
323
|
|
|
275
324
|
```tsx
|
|
276
|
-
import {
|
|
325
|
+
import { StyleSheet, UnistyleDependency, UnistylesRuntime } from 'react-native-unistyles'
|
|
277
326
|
|
|
278
327
|
// Listen for Unistyles theme changes and sync
|
|
279
328
|
StyleSheet.addChangeListener((deps) => {
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This skill was copied from the latent-spaces brag repository.
|
|
4
4
|
|
|
5
|
-
- Source: https://github.com/latent-spaces/brag/tree/
|
|
6
|
-
- Source commit:
|
|
7
|
-
- Source SHA-256 (`skills/brag-slim/SKILL.md`):
|
|
5
|
+
- Source: https://github.com/latent-spaces/brag/tree/069432cac935ed1895859df201c31436c07fb74e/skills/brag-slim
|
|
6
|
+
- Source commit: 069432cac935ed1895859df201c31436c07fb74e
|
|
7
|
+
- Source SHA-256 (`skills/brag-slim/SKILL.md`): 3079af81f4239682fb2d1d6a1a008f1542b20bee8a3ceb06030e2fcae38b2e29
|
|
8
8
|
- License: MIT
|
|
9
9
|
- Copyright: Copyright (c) 2026 Shunit Haviv Hakimi
|
|
10
10
|
|
|
@@ -36,6 +36,8 @@ Read the code: the main page, styles (exact colors and fonts), README, routes an
|
|
|
36
36
|
|
|
37
37
|
You have the source, so use it directly: import or render the project's real components, stylesheets, fonts, images and animations in the video instead of rebuilding them.
|
|
38
38
|
|
|
39
|
+
Don't read build output (`dist/`, `.next/`, `build/`), lock files, test files, `.git/`, env and secret files (`.env`, `.env.*`), key and credential material (`.pem`, `.key`, `id_rsa`, service-account JSON, anything under `secrets/` or `credentials/`), local config that commonly holds tokens, or anything `.gitignore` excludes for those reasons.
|
|
40
|
+
|
|
39
41
|
### Website
|
|
40
42
|
|
|
41
43
|
Get the site as a visitor sees it. Many sites build their page with JavaScript, so a plain download can come back as an almost empty shell. If it does, load the page in a headless browser to get the rendered result. Dismiss cookie banners and other overlays, and scroll section by section, since content that animates in on scroll stays blank in a single full-page capture.
|
|
@@ -50,6 +52,8 @@ Get the site as a visitor sees it. Many sites build their page with JavaScript,
|
|
|
50
52
|
|
|
51
53
|
Before planning, answer: What is it (one sentence)? Who is it for, and what does it do for them? What sets it apart? What's the most impressive or funniest claim? What's the visual hook? What real UI or flow should be shown? What tone fits? What's the one-line share caption?
|
|
52
54
|
|
|
55
|
+
Everything gathered here can end up in a public video. Never carry secrets, API keys, tokens, internal hostnames or URLs, real customer or user names, email addresses, or other personal data into the plan, the video, or the share copy. If the real UI shows such data, swap in plausible fictional stand-ins and say so in the plan.
|
|
56
|
+
|
|
53
57
|
## 2. Plan
|
|
54
58
|
|
|
55
59
|
Write `brag-plan.md`: the angle, the hook, 2–3 highlights, the punchline, tone, visual identity, and a scene-by-scene storyboard with durations that sum to the target.
|