fiboui 2.4.4 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,61 +1,61 @@
1
1
  <div align="center">
2
2
 
3
- ```
4
- ███████╗██╗██████╗ ██████╗ ██╗ ██╗██╗
5
- ██╔════╝██║██╔══██╗██╔═══██╗██║ ██║██║
6
- █████╗ ██║██████╔╝██║ ██║██║ ██║██║
7
- ██╔══╝ ██║██╔══██╗██║ ██║██║ ██║██║
8
- ██║ ██║██████╔╝╚██████╔╝╚██████╔╝██║
9
- ╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═════╝ ╚═╝
10
- ```
3
+ <img src="./docs/brand/logo.svg" width="88" alt="FiboUI logo" />
11
4
 
12
5
  # FiboUI
13
6
 
14
- **Fluent React UI.** Flutter & SwiftUI energy — chainable builders, signals, themes.
15
-
16
- Builders **are** React elements. Return them from functions. Skip `.build()`. Prefer the fluent API — no JSX tags.
7
+ **Fluent React UI.** Flutter & SwiftUI energy for the web.
8
+ There is no JSX — the function return **is** the view.
17
9
 
18
10
  <br />
19
11
 
20
- [![npm](https://img.shields.io/npm/v/fiboui?style=flat-square&color=ff2d8a)](https://www.npmjs.com/package/fiboui)
21
- [![license](https://img.shields.io/npm/l/fiboui?style=flat-square)](./LICENSE)
22
- [![site](https://img.shields.io/badge/site-fiboui.vercel.app-0a0a0a?style=flat-square)](https://fiboui.vercel.app)
23
- [![store](https://img.shields.io/badge/demo-fiboui--store-c8ff00?style=flat-square&labelColor=0a0a0a)](https://fiboui-store.vercel.app)
12
+ [![npm](https://img.shields.io/npm/v/fiboui?style=for-the-badge&color=ff2d8a&labelColor=0a0a0a)](https://www.npmjs.com/package/fiboui)
13
+ [![downloads](https://img.shields.io/npm/dm/fiboui?style=for-the-badge&color=c8ff00&labelColor=0a0a0a)](https://www.npmjs.com/package/fiboui)
14
+ [![license](https://img.shields.io/badge/license-MIT-0a0a0a?style=for-the-badge&labelColor=0a0a0a&color=ffffff)](https://github.com/felipeoliveiradev/fiboui)
15
+ [![site](https://img.shields.io/badge/site-fiboui.vercel.app-0a0a0a?style=for-the-badge&labelColor=ff2d8a&color=0a0a0a)](https://fiboui.vercel.app)
24
16
 
25
- **Live**
26
- [`fiboui.vercel.app`](https://fiboui.vercel.app)
27
- ·
28
- **Store demo**
29
- [`fiboui-store.vercel.app`](https://fiboui-store.vercel.app)
30
- ·
31
- **npm**
32
- [`fiboui`](https://www.npmjs.com/package/fiboui)
17
+ <br />
33
18
 
34
- ```bash
35
- npm install fiboui
36
- ```
19
+ <img src="./docs/brand/banner.png" width="960" alt="FiboUI — Fluent React UI. There is no JSX." />
37
20
 
38
21
  </div>
39
22
 
40
23
  ---
41
24
 
42
- ## Why FiboUI
25
+ <div align="center">
43
26
 
44
- | | |
45
- | :--- | :--- |
46
- | **Assembly pattern** | Factories return builders for endless chaining |
47
- | **Zero-build children** | Pass builders to `.children()` — they finalize implicitly |
48
- | **Signals** | `signal()`, `computed()`, `.bindSignal()`, `.observer()` |
49
- | **Themes** | `.theme("noir")` · `extendTheme` · Material / Cupertino / Web / Noir |
50
- | **Motion** | `.animate('fadeIn')` · `.onScroll` · `.hoverEffect` · CSS-first |
51
- | **Type-safe** | TypeScript builders · `FiboChild` / `FiboChildren` |
27
+ ### Live product
28
+
29
+ | Marketing site | Store demo |
30
+ | :---: | :---: |
31
+ | [![FiboUI site](./docs/brand/site-hero.png)](https://fiboui.vercel.app) | [![Fibo Store](./docs/brand/store-hero.png)](https://fiboui-store.vercel.app) |
32
+ | [**fiboui.vercel.app**](https://fiboui.vercel.app) | [**fiboui-store.vercel.app**](https://fiboui-store.vercel.app) |
33
+
34
+ Both ships are built **only** with FiboUI fluent builders — no JSX in the product UI.
35
+
36
+ </div>
52
37
 
53
38
  ---
54
39
 
55
- ## Quick start
40
+ ## Cursor / VS Code extension
41
+
42
+ Fluent trees get Flutter-style **closing labels** (`// Column`, `// List`, `// Form`), **auto-indent** on Enter, **lineage guides** on `.children([…])`, snippets (`fcol`, `frow`, …), chain autocomplete, and the **FiboUI Noir** colour theme.
43
+
44
+ ```bash
45
+ ln -sfn "$(pwd)/extensions/vscode-fiboui" \
46
+ "$HOME/.cursor/extensions/felipeoliveiradev.fiboui-0.1.0"
47
+ ```
48
+
49
+ Reload the window, then pick theme **FiboUI Noir**. Details: [`extensions/vscode-fiboui/README.md`](./extensions/vscode-fiboui/README.md).
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ npm install fiboui
55
+ ```
56
56
 
57
57
  ```tsx
58
- import 'fiboui/style.css'
58
+ import 'fiboui/style.css' // required once — JS does not load CSS
59
59
  import { Button, Column, Text, mount } from 'fiboui'
60
60
 
61
61
  function App() {
@@ -71,33 +71,59 @@ function App() {
71
71
  mount('#root', App)
72
72
  ```
73
73
 
74
- **Required:** import `'fiboui/style.css'` once — the JS entry does not load CSS.
75
- ESM-only (`import`, no `require`). Peer deps: **React 18 or 19**.
74
+ ESM-only · React **18 / 19** · Next App Router → `'use client'` on files that call builders.
75
+
76
+ ---
76
77
 
77
- Next.js App Router: files that **call** builders must be Client Components (`'use client'`).
78
+ ## JSX vs FiboUI
79
+
80
+ ```tsx
81
+ // ── JSX ──────────────────────────────────
82
+ <div className="flex flex-col gap-3 p-6">
83
+ <h1>Hello</h1>
84
+ <button onClick={onShip}>Ship it</button>
85
+ </div>
86
+
87
+ // ── FiboUI ───────────────────────────────
88
+ Column()
89
+ .gap(12)
90
+ .padding(24)
91
+ .children([
92
+ Text('Hello').variant('h1'),
93
+ Button('Ship it').onPress(onShip),
94
+ ])
95
+ ```
96
+
97
+ Same tree. Method calls instead of tags. Layout, theme, motion, and reactivity stay on the builder.
78
98
 
79
99
  ---
80
100
 
81
- ## Taste of the API
101
+ ## Runtime flow
82
102
 
83
- ### Builders (no `.build()`)
103
+ <img src="./docs/brand/flow-runtime.png" width="960" alt="Factory → fluent chain → children → React element → mount" />
84
104
 
85
- ```tsx
86
- import { Card, Text } from 'fiboui'
105
+ ```mermaid
106
+ flowchart LR
107
+ A["Column()"] --> B[".gap().padding()"]
108
+ B --> C[".children([...])"]
109
+ C --> D["React element"]
110
+ D --> E["mount / return"]
87
111
 
88
- function Hello() {
89
- return Card()
90
- .padding(32)
91
- .bg('#111')
92
- .children([Text('Hello').variant('h2')])
93
- }
112
+ style A fill:#141414,stroke:#fff,color:#fff
113
+ style B fill:#141414,stroke:#ff2d8a,color:#ff2d8a
114
+ style C fill:#141414,stroke:#c8ff00,color:#c8ff00
115
+ style D fill:#141414,stroke:#fff,color:#fff
116
+ style E fill:#c8ff00,stroke:#c8ff00,color:#0a0a0a
94
117
  ```
95
118
 
96
- `Button` uses **`.onPress`** (not `onClick`).
119
+ Builders **are** valid React elements (`isValidElement(Button('Go'))`).
120
+ Return them. Nest them. **Skip `.build()`.**
97
121
 
98
- ### Signals
122
+ ---
123
+
124
+ ## Signal flow
99
125
 
100
- `.bindSignal(sig)` re-assembles when the signal changes. Read values inside a **function child**:
126
+ <img src="./docs/brand/flow-signals.png" width="960" alt="signal → bindSignal → function children → UI" />
101
127
 
102
128
  ```tsx
103
129
  import { Box, Button, Text, signal } from 'fiboui'
@@ -114,6 +140,61 @@ Box()
114
140
  ])
115
141
  ```
116
142
 
143
+ `.bindSignal` re-assembles. Read `.value` inside a **function child** so updates are live. `` Text(`Total ${todos.$length}`) `` stays live without a function child. Forms and validation: [Form](docs/components/interactive-form.md).
144
+
145
+ ```mermaid
146
+ sequenceDiagram
147
+ participant UI as Builder tree
148
+ participant S as signal(count)
149
+ participant H as onPress
150
+
151
+ UI->>S: .bindSignal(count)
152
+ H->>S: count.value += 1
153
+ S-->>UI: notify subscribers
154
+ UI->>UI: re-assemble children()
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Package architecture
160
+
161
+ <img src="./docs/brand/flow-architecture.png" width="960" alt="App over layout/content/structure/theme/reactivity over core" />
162
+
163
+ ```mermaid
164
+ flowchart TB
165
+ APP["your app — screens · domain · mount"]
166
+ subgraph builders["fluent builders"]
167
+ L["layout / content<br/>Column · Row · Text · Button"]
168
+ S["structure / nav<br/>Box · Grid · Scaffold"]
169
+ T["theme / motion<br/>noir · animate · hover"]
170
+ R["reactivity<br/>signal · computed · store"]
171
+ end
172
+ CORE["core — FiboBuilder · styleManager · bindSignal"]
173
+
174
+ APP --> L & S & T & R
175
+ L & S & T & R --> CORE
176
+
177
+ style APP fill:#141414,stroke:#c8ff00,color:#c8ff00
178
+ style CORE fill:#c8ff00,stroke:#c8ff00,color:#0a0a0a
179
+ style L fill:#141414,stroke:#ff2d8a,color:#ff2d8a
180
+ style S fill:#141414,stroke:#fff,color:#fff
181
+ style T fill:#141414,stroke:#fff,color:#fff
182
+ style R fill:#141414,stroke:#fff,color:#fff
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Why FiboUI
188
+
189
+ | | |
190
+ | :--- | :--- |
191
+ | **Assembly pattern** | Factories return builders for endless chaining |
192
+ | **Zero-build children** | Pass builders to `.children()` — they finalize implicitly |
193
+ | **Signals** | `signal()`, `computed()`, `.bindSignal()`, `.observer()` |
194
+ | **Themes** | `.theme("noir")` · `extendTheme` · Material / Cupertino / Web / Noir |
195
+ | **Motion** | `.animate('fadeIn')` · `.onScroll` · `.hoverEffect` · CSS-first |
196
+ | **Type-safe** | TypeScript builders · `FiboChild` / `FiboChildren` |
197
+
117
198
  ### Themes & motion
118
199
 
119
200
  ```tsx
@@ -122,17 +203,11 @@ Box()
122
203
  .animate('fadeIn')
123
204
  .ease('spring')
124
205
  .hover((h) => h.effect('sweepToRight'))
125
- ```
126
206
 
127
- Responsive:
128
-
129
- ```tsx
130
207
  Box().padding(8).md({ padding: 16 }).lg({ padding: 24 })
131
208
  ```
132
209
 
133
- ---
134
-
135
- ## Layout notes
210
+ ### Layout notes
136
211
 
137
212
  FiboUI **2.x** matches Flutter / SwiftUI: `Column` defaults to `crossAxisAlignment('center')`.
138
213
  `Row` uses `align-self: stretch` so `spaceBetween` still fills width.
@@ -141,26 +216,41 @@ FiboUI **2.x** matches Flutter / SwiftUI: `Column` defaults to `crossAxisAlignme
141
216
  Column().crossAxisAlignment('stretch')
142
217
  ```
143
218
 
144
- `Scaffold` uses `headerBar`, `footerBar`, `sideBarLeft`, `sideBarRight`.
219
+ `Button` uses **`.onPress`** (not `onClick`).
145
220
 
146
221
  ---
147
222
 
148
- ## Live demos
223
+ ## Brand
149
224
 
150
- | | |
151
- | :--- | :--- |
152
- | **[fiboui.vercel.app](https://fiboui.vercel.app)** | Marketing site — builders, signals, theme, motion, media |
153
- | **[fiboui-store.vercel.app](https://fiboui-store.vercel.app)** | Full retail demo — catalog → bag → checkout |
225
+ <div align="center">
154
226
 
155
- Both are built **only** with FiboUI fluent builders.
227
+ <img src="./docs/brand/logo-lockup.svg" width="280" alt="FiboUI lockup" />
228
+
229
+ <br /><br />
230
+
231
+ | Token | Hex | |
232
+ | :---: | :---: | :--- |
233
+ | **Ink** | `#0a0a0a` | background |
234
+ | **Chalk** | `#ffffff` | type |
235
+ | **Pink** | `#ff2d8a` | energy |
236
+ | **Lime** | `#c8ff00` | mark / CTA |
237
+
238
+ <img src="./docs/brand/fibonacci.svg" width="220" alt="Fibonacci spiral" />
239
+
240
+ **Tailored to each request** · **Attention to detail**
241
+
242
+ </div>
156
243
 
157
244
  ---
158
245
 
159
246
  ## Docs & contributing
160
247
 
161
- - Migration from 1.x → [MIGRATION.md](./MIGRATION.md)
162
- - Contributing & release → [CONTRIBUTING.md](./CONTRIBUTING.md)
163
- - Animation guide → `docs/guide/animation.md`
248
+ | | |
249
+ | :--- | :--- |
250
+ | Migration from 1.x | [MIGRATION.md](./MIGRATION.md) |
251
+ | Contributing & release | [CONTRIBUTING.md](./CONTRIBUTING.md) |
252
+ | Animation guide | [`docs/guide/animation.md`](./docs/guide/animation.md) |
253
+ | Brand assets | [`docs/brand/`](./docs/brand/) |
164
254
 
165
255
  Publishing is automated on **`main`** (GitHub Actions + `NPM_TOKEN`). Prefer not to `npm publish` locally.
166
256
 
@@ -168,6 +258,10 @@ Publishing is automated on **`main`** (GitHub Actions + `NPM_TOKEN`). Prefer not
168
258
 
169
259
  <div align="center">
170
260
 
261
+ <img src="./docs/brand/logo-mark.svg" width="48" alt="" />
262
+
263
+ <br /><br />
264
+
171
265
  **Wear the return.**
172
266
 
173
267
  MIT © 2025–2026 FiboUI
@@ -0,0 +1,50 @@
1
+ import { jsx as u } from "react/jsx-runtime";
2
+ import { aa as m, as as p, a9 as v } from "./client-C9ZVisXx.js";
3
+ const k = ({
4
+ to: t,
5
+ children: c,
6
+ replace: n = !1,
7
+ state: e,
8
+ className: l,
9
+ style: f,
10
+ onClick: i
11
+ }) => {
12
+ const o = m(), a = p(), r = t.startsWith("http") || t.startsWith("//") || t.startsWith("#") ? t : `${(a == null ? void 0 : a.basename) ?? ""}${t}`;
13
+ return /* @__PURE__ */ u(
14
+ "a",
15
+ {
16
+ href: r,
17
+ onClick: (s) => {
18
+ s.ctrlKey || s.metaKey || s.shiftKey || s.button !== 0 || (s.preventDefault(), i && i(s), o(t, { replace: n, state: e }));
19
+ },
20
+ className: l,
21
+ style: f,
22
+ children: c
23
+ }
24
+ );
25
+ }, W = ({
26
+ to: t,
27
+ children: c,
28
+ className: n = "",
29
+ style: e = {},
30
+ activeClassName: l = "active",
31
+ activeStyle: f = {},
32
+ exact: i = !1,
33
+ ...o
34
+ }) => {
35
+ const { currentPath: a } = v(), r = i ? a === t : a.startsWith(t), h = r ? `${n} ${l}`.trim() : n, s = r ? { ...e, ...f } : e;
36
+ return /* @__PURE__ */ u(
37
+ k,
38
+ {
39
+ to: t,
40
+ className: h,
41
+ style: s,
42
+ ...o,
43
+ children: c
44
+ }
45
+ );
46
+ };
47
+ export {
48
+ k as L,
49
+ W as N
50
+ };
@@ -1,7 +1,6 @@
1
- "use client";
2
1
  var h = Object.defineProperty;
3
- var g = (c, t, e) => t in c ? h(c, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[t] = e;
4
- var s = (c, t, e) => g(c, typeof t != "symbol" ? t + "" : t, e);
2
+ var g = (a, t, e) => t in a ? h(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
3
+ var s = (a, t, e) => g(a, typeof t != "symbol" ? t + "" : t, e);
5
4
  const n = class n {
6
5
  constructor() {
7
6
  s(this, "services", /* @__PURE__ */ new Map());
@@ -49,8 +48,8 @@ const n = class n {
49
48
  }
50
49
  };
51
50
  s(n, "instance");
52
- let a = n;
53
- const l = a.getInstance(), i = class i {
51
+ let c = n;
52
+ const f = c.getInstance(), i = class i {
54
53
  constructor() {
55
54
  s(this, "plugins", /* @__PURE__ */ new Map());
56
55
  s(this, "routes", []);
@@ -67,7 +66,7 @@ const l = a.getInstance(), i = class i {
67
66
  return this.plugins.has(t.name) ? this : (this.plugins.set(t.name, t), t.setup(this), this);
68
67
  }
69
68
  registerService(t, e) {
70
- l.register(t, e);
69
+ f.register(t, e);
71
70
  }
72
71
  registerStore(t, e) {
73
72
  const r = e ?? `store-${this.storeSeq++}`;