@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.
Files changed (110) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +8 -8
  3. package/dist/src/installers/superpowers.js +23 -7
  4. package/dist/src/installers/superpowers.js.map +1 -1
  5. package/package.json +5 -5
  6. package/skills/backend/fastify-best-practices/NOTICE.md +1 -1
  7. package/skills/backend/fastify-best-practices/rules/authentication.md +13 -0
  8. package/skills/backend/fastify-best-practices/rules/configuration.md +9 -0
  9. package/skills/backend/fastify-best-practices/rules/content-type.md +16 -0
  10. package/skills/backend/fastify-best-practices/rules/cors-security.md +18 -0
  11. package/skills/backend/fastify-best-practices/rules/database.md +12 -0
  12. package/skills/backend/fastify-best-practices/rules/decorators.md +14 -0
  13. package/skills/backend/fastify-best-practices/rules/deployment.md +16 -0
  14. package/skills/backend/fastify-best-practices/rules/error-handling.md +16 -0
  15. package/skills/backend/fastify-best-practices/rules/hooks.md +20 -0
  16. package/skills/backend/fastify-best-practices/rules/http-proxy.md +11 -0
  17. package/skills/backend/fastify-best-practices/rules/logging.md +18 -0
  18. package/skills/backend/fastify-best-practices/rules/performance.md +20 -0
  19. package/skills/backend/fastify-best-practices/rules/plugins.md +14 -0
  20. package/skills/backend/fastify-best-practices/rules/routes.md +18 -0
  21. package/skills/backend/fastify-best-practices/rules/schemas.md +20 -0
  22. package/skills/backend/fastify-best-practices/rules/serialization.md +19 -0
  23. package/skills/backend/fastify-best-practices/rules/testing.md +17 -0
  24. package/skills/backend/fastify-best-practices/rules/typescript.md +15 -0
  25. package/skills/backend/fastify-best-practices/rules/websockets.md +15 -0
  26. package/skills/backend/go/golang-patterns/NOTICE.md +1 -1
  27. package/skills/backend/go/golang-patterns/SKILL.md +2 -1
  28. package/skills/devops/docker-patterns/NOTICE.md +1 -1
  29. package/skills/devops/docker-patterns/SKILL.md +3 -3
  30. package/skills/frontend/design/revenue-centric-design/NOTICE.md +1 -1
  31. package/skills/frontend/design/revenue-centric-design/SKILL.md +6 -4
  32. package/skills/frontend/design/revenue-centric-design/assets/1985681720104903142__1.jpg +0 -0
  33. package/skills/frontend/design/revenue-centric-design/assets/1999584679247134761__1.jpg +0 -0
  34. package/skills/frontend/design/revenue-centric-design/assets/2000930776636940333__1.jpg +0 -0
  35. package/skills/frontend/design/revenue-centric-design/assets/2018693884449009956__3.jpg +0 -0
  36. package/skills/frontend/design/revenue-centric-design/assets/2081714430811730162__1.jpg +0 -0
  37. package/skills/frontend/design/revenue-centric-design/assets/2092692547244007852__q__1.jpg +0 -0
  38. package/skills/frontend/design/revenue-centric-design/assets/2092692547244007852__q__2.jpg +0 -0
  39. package/skills/frontend/design/revenue-centric-design/assets/2092692547244007852__q__3.jpg +0 -0
  40. package/skills/frontend/design/revenue-centric-design/references/checkout-and-forms.md +39 -0
  41. package/skills/frontend/design/revenue-centric-design/references/churn-and-retention.md +25 -0
  42. package/skills/frontend/design/revenue-centric-design/references/conversion-and-landing-pages.md +52 -1
  43. package/skills/frontend/design/revenue-centric-design/references/dashboards-and-data-viz.md +23 -0
  44. package/skills/frontend/design/revenue-centric-design/references/metrics-and-experimentation.md +13 -0
  45. package/skills/frontend/design/revenue-centric-design/references/onboarding-and-activation.md +7 -1
  46. package/skills/frontend/design/revenue-centric-design/references/pricing-and-monetization.md +35 -8
  47. package/skills/frontend/design/revenue-centric-design/references/product-strategy-and-features.md +37 -0
  48. package/skills/frontend/design/revenue-centric-design/references/revenue-centric-design.md +2 -2
  49. package/skills/frontend/design/ui-ux-pro-max/NOTICE.md +6 -4
  50. package/skills/frontend/design/ui-ux-pro-max/SKILL.md +103 -573
  51. package/skills/frontend/design/ui-ux-pro-max/data/app-interface.csv +29 -27
  52. package/skills/frontend/design/ui-ux-pro-max/data/catalog-summary.json +78 -0
  53. package/skills/frontend/design/ui-ux-pro-max/data/charts.csv +26 -26
  54. package/skills/frontend/design/ui-ux-pro-max/data/colors.csv +191 -160
  55. package/skills/frontend/design/ui-ux-pro-max/data/data-provenance.json +1348 -0
  56. package/skills/frontend/design/ui-ux-pro-max/data/google-font-licenses.json +20185 -0
  57. package/skills/frontend/design/ui-ux-pro-max/data/google-fonts.csv +1934 -1923
  58. package/skills/frontend/design/ui-ux-pro-max/data/icons.csv +106 -106
  59. package/skills/frontend/design/ui-ux-pro-max/data/landing.csv +35 -35
  60. package/skills/frontend/design/ui-ux-pro-max/data/motion.csv +18 -0
  61. package/skills/frontend/design/ui-ux-pro-max/data/phosphor-icons-upstream.json +32582 -0
  62. package/skills/frontend/design/ui-ux-pro-max/data/products.csv +192 -161
  63. package/skills/frontend/design/ui-ux-pro-max/data/react-performance.csv +37 -37
  64. package/skills/frontend/design/ui-ux-pro-max/data/stacks/angular.csv +51 -51
  65. package/skills/frontend/design/ui-ux-pro-max/data/stacks/astro.csv +54 -54
  66. package/skills/frontend/design/ui-ux-pro-max/data/stacks/avalonia.csv +57 -0
  67. package/skills/frontend/design/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
  68. package/skills/frontend/design/ui-ux-pro-max/data/stacks/html-tailwind.csv +60 -56
  69. package/skills/frontend/design/ui-ux-pro-max/data/stacks/javafx.csv +76 -0
  70. package/skills/frontend/design/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
  71. package/skills/frontend/design/ui-ux-pro-max/data/stacks/laravel.csv +51 -51
  72. package/skills/frontend/design/ui-ux-pro-max/data/stacks/nextjs.csv +62 -53
  73. package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxt-ui.csv +77 -51
  74. package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxtjs.csv +68 -59
  75. package/skills/frontend/design/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
  76. package/skills/frontend/design/ui-ux-pro-max/data/stacks/react.csv +67 -54
  77. package/skills/frontend/design/ui-ux-pro-max/data/stacks/shadcn.csv +69 -61
  78. package/skills/frontend/design/ui-ux-pro-max/data/stacks/svelte.csv +56 -54
  79. package/skills/frontend/design/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
  80. package/skills/frontend/design/ui-ux-pro-max/data/stacks/threejs.csv +54 -54
  81. package/skills/frontend/design/ui-ux-pro-max/data/stacks/uno.csv +60 -0
  82. package/skills/frontend/design/ui-ux-pro-max/data/stacks/uwp.csv +56 -0
  83. package/skills/frontend/design/ui-ux-pro-max/data/stacks/vue.csv +50 -50
  84. package/skills/frontend/design/ui-ux-pro-max/data/stacks/winui.csv +60 -0
  85. package/skills/frontend/design/ui-ux-pro-max/data/stacks/wpf.csv +57 -0
  86. package/skills/frontend/design/ui-ux-pro-max/data/styles.csv +89 -85
  87. package/skills/frontend/design/ui-ux-pro-max/data/typography.csv +74 -73
  88. package/skills/frontend/design/ui-ux-pro-max/data/ui-reasoning.csv +193 -162
  89. package/skills/frontend/design/ui-ux-pro-max/data/ux-guidelines.csv +30 -10
  90. package/skills/frontend/design/ui-ux-pro-max/references/pro-rules.md +117 -0
  91. package/skills/frontend/design/ui-ux-pro-max/references/quick-reference.md +256 -0
  92. package/skills/frontend/design/ui-ux-pro-max/scripts/core.py +800 -69
  93. package/skills/frontend/design/ui-ux-pro-max/scripts/design_system.py +700 -180
  94. package/skills/frontend/design/ui-ux-pro-max/scripts/reasoning_contract.py +123 -0
  95. package/skills/frontend/design/ui-ux-pro-max/scripts/search.py +105 -42
  96. package/skills/frontend/design/ui-ux-pro-max/scripts/validate_data.py +1095 -0
  97. package/skills/frontend/react-native/react-native-unistyles-v3/NOTICE.md +1 -1
  98. package/skills/frontend/react-native/react-native-unistyles-v3/SKILL.md +33 -24
  99. package/skills/frontend/react-native/react-native-unistyles-v3/references/api-reference.md +135 -78
  100. package/skills/frontend/react-native/react-native-unistyles-v3/references/common-issues.md +48 -31
  101. package/skills/frontend/react-native/react-native-unistyles-v3/references/setup-guide.md +76 -34
  102. package/skills/frontend/react-native/react-native-unistyles-v3/references/styling-patterns.md +145 -52
  103. package/skills/frontend/react-native/react-native-unistyles-v3/references/third-party-integration.md +76 -27
  104. package/skills/media/brag-slim/NOTICE.md +3 -3
  105. package/skills/media/brag-slim/SKILL.md +4 -0
  106. package/tools.lock.json +20 -20
  107. package/skills/frontend/design/revenue-centric-design/assets/2018693884449009956__1.jpg +0 -0
  108. package/skills/frontend/design/ui-ux-pro-max/data/_sync_all.py +0 -414
  109. package/skills/frontend/design/ui-ux-pro-max/data/design.csv +0 -1776
  110. package/skills/frontend/design/ui-ux-pro-max/data/draft.csv +0 -1779
@@ -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 `shadowOffset`), use breakpoints at the nested level:
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, 576)]: 8, // width <= 576
310
- [mq.only.width(576, 768)]: 16, // 576 < width <= 768
311
- [mq.only.width(768)]: 24, // width > 768
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, 768)]: 'none',
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
- ### Mixing breakpoint names and pixel values
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') // between sm and lg breakpoints
327
- mq.only.width(320, 768) // between 320px and 768px
328
- mq.only.height(400) // height > 400px
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, 768).and.height(null, 500)]: 'column', // small screen
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
- ### Pseudo-classes
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: [{ scale: 0.98 }],
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
- _focusVisible: {
561
+ '_focus-visible': {
516
562
  outlineStyle: 'dashed',
517
563
  },
518
- _focusWithin: {
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
- Supported pseudo-classes: `_hover`, `_active`, `_focus`, `_disabled`, `_focusVisible`, `_focusWithin`.
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-only'
600
+ import { getWebProps } from 'react-native-unistyles/web'
544
601
 
545
602
  const CustomWebComponent = () => {
546
- const { className, style } = getWebProps(styles.container)
547
- return <div className={className} style={style}>Content</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
- const animatedColor = useAnimatedVariantColor(styles.button, 'backgroundColor')
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, animatedColor]} />
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 { useServerUnistyles } from 'react-native-unistyles'
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
- <head>{styles}</head>
626
- <body>{children}</body>
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 function Document() {
645
- const styles = getServerUnistyles()
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
- return (
648
- <Html>
649
- <Head>{styles}</Head>
650
- <body><Main /><NextScript /></body>
651
- </Html>
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
- hydrateServerUnistyles()
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 height, replacing `react-native-reanimated`'s `useAnimatedKeyboard`:
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.
@@ -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 third-party components that need theme-derived **non-style props** (e.g., `color`, `size`, `tintColor`).
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
- ### Static mappings vs uniProps
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
- By default, the Babel plugin only processes files inside the `root` directory. For files outside `root` (e.g., shared packages in a monorepo), add their paths:
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
- '../packages/shared-ui/src',
83
- '../packages/design-system/src',
109
+ 'external-library/components',
110
+ 'my-ui-kit/src',
84
111
  ],
85
112
  }]
86
113
  ]
87
114
  }
88
115
  ```
89
116
 
90
- **Important:** Paths are relative to the project root (where babel.config.js lives).
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
- Process files that import from custom package names (useful for internal packages that re-export components):
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: ['@myorg/ui', '@myorg/shared-components'],
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 from `@myorg/ui`, process the components in that file the same way as standard React Native components."
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
- Map exotic component imports to Unistyles component factories. Useful when a library exports components with non-standard names that the plugin can't detect:
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
- '@expo/vector-icons': {
126
- 'MaterialIcons': 'Text', // treat as Text factory
127
- 'FontAwesome': 'Text',
128
- },
129
- 'react-native-svg': {
130
- 'Svg': 'View', // treat as View factory
131
- 'Circle': 'View',
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
- ## react-native-edge-to-edge
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
- ```bash
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 { UnistylesRuntime, StyleSheet } from 'react-native-unistyles'
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/fd7de7e418334876b3ea4e9258231a66a2c2a38d/skills/brag-slim
6
- - Source commit: fd7de7e418334876b3ea4e9258231a66a2c2a38d
7
- - Source SHA-256 (`skills/brag-slim/SKILL.md`): c97ea53d7c5df2a3dd64694a388c013a05c363ac7c2e4e0d956c18ad3bfaa5ee
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.