fiboui 1.0.0 → 1.0.1
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 +144 -73
- package/dist/core/StateWrapper.d.ts +3 -0
- package/dist/core/builder.d.ts +4 -1
- package/dist/core/effects.d.ts +4 -3
- package/dist/core/hooks.d.ts +5 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/state.d.ts +76 -27
- package/dist/effects-D16XdB_d.mjs +10 -0
- package/dist/index.esm.js +1181 -1026
- package/dist/index.umd.js +4 -4
- package/dist/interactive/TextField/index.d.ts +3 -2
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/core/StateWrapper.tsx +28 -2
- package/src/core/builder.ts +48 -10
- package/src/core/effects.ts +3 -3
- package/src/core/hooks.ts +48 -0
- package/src/core/index.ts +1 -0
- package/src/core/state.ts +203 -139
- package/src/demo.tsx +5 -0
- package/src/interactive/Button/index.ts +2 -1
- package/src/interactive/TextField/index.ts +29 -6
- package/src/structure/Box/index.ts +3 -2
- package/dist/effects-Co9C_Dyx.mjs +0 -9
- package/dist/examples/ScaffoldExamples.d.ts +0 -3
- package/dist/examples/StateExamples.d.ts +0 -5
- package/src/examples/ScaffoldExamples.tsx +0 -299
- package/src/examples/StateExamples.tsx +0 -149
package/README.md
CHANGED
|
@@ -1,101 +1,172 @@
|
|
|
1
|
-
# FiboUI
|
|
1
|
+
# 🏗️ FiboUI v1.0.0
|
|
2
2
|
|
|
3
|
-
A Flutter
|
|
3
|
+
**A Flutter & SwiftUI-inspired React UI framework featuring a powerful Assembly Pattern and high-fidelity reactivity.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
FiboUI brings the expressive, chainable syntax of modern mobile frameworks to React. Build complex, beautiful, and highly-performant UIs with **zero boilerplate** and **maximum readability**.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🏗️ **The Assembly Pattern** - Components return builders for endless chaining.
|
|
12
|
+
- ⚡ **Zero-Build Children** - Pass builders directly to `.children()`; they build implicitly.
|
|
13
|
+
- 🔬 **Fine-Grained Reactivity** - Native support for Signals, Computed, and Observables.
|
|
14
|
+
- 🎭 **Dynamic Multi-Theme** - Material, Cupertino, and Web themes with instant global switching.
|
|
15
|
+
- 🎨 **Premium Aesthetics** - Built-in glassmorphism, micro-animations, and sleek dark modes.
|
|
16
|
+
- 🔷 **100% Type-Safe** - Built with TypeScript for the best developer experience.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 🚀 Installation
|
|
6
21
|
|
|
7
22
|
```bash
|
|
8
23
|
npm install fiboui
|
|
9
24
|
```
|
|
10
25
|
|
|
11
|
-
|
|
26
|
+
Import the styles in your main entry file:
|
|
12
27
|
|
|
13
28
|
```tsx
|
|
14
|
-
import { FiboThemeProvider, Container, Text, Button, Row } from 'fiboui';
|
|
15
29
|
import 'fiboui/dist/style.css';
|
|
30
|
+
```
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.children([
|
|
31
|
-
Button("Click me")
|
|
32
|
-
.variant("elevated")
|
|
33
|
-
.onPress(() => console.log("Clicked!")),
|
|
34
|
-
|
|
35
|
-
Button("Outlined")
|
|
36
|
-
.variant("outlined")
|
|
37
|
-
])
|
|
38
|
-
])
|
|
39
|
-
.build()}
|
|
40
|
-
</FiboThemeProvider>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🏗️ The Assembly Pattern
|
|
35
|
+
|
|
36
|
+
### 1. Components as Builders
|
|
37
|
+
Components return builder instances, allowing customization before rendering.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
StakentCard()
|
|
41
|
+
.className("p-8 hover:border-indigo-500/50")
|
|
42
|
+
.style({ backgroundColor: '#111' })
|
|
43
|
+
.children([ ... ])
|
|
44
|
+
.build()
|
|
43
45
|
```
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
### 2. Implicit Construction
|
|
48
|
+
Builders in `.children()` are automatically finalized.
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
```tsx
|
|
51
|
+
Column().children([
|
|
52
|
+
Text("Title").variant("h1"),
|
|
53
|
+
Button("Action").onClick(handlePress)
|
|
54
|
+
]).build()
|
|
55
|
+
```
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
---
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
## ⚡ Reactivity & State
|
|
56
60
|
|
|
61
|
+
### Signals (Primitives)
|
|
57
62
|
```tsx
|
|
58
|
-
|
|
63
|
+
const count = signal(0);
|
|
64
|
+
|
|
65
|
+
Box()
|
|
66
|
+
.bindSignal(count)
|
|
67
|
+
.children([
|
|
68
|
+
Text(`Count: ${count.value}`),
|
|
69
|
+
Button("+").onPress(() => count.value++)
|
|
70
|
+
])
|
|
71
|
+
.build()
|
|
72
|
+
```
|
|
59
73
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
### Global Store
|
|
75
|
+
```tsx
|
|
76
|
+
const store = createStore({ theme: 'dark', user: 'John' });
|
|
77
|
+
|
|
78
|
+
Box().observer().children([
|
|
79
|
+
Text(store.getState().user)
|
|
80
|
+
])
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 📱 Scaffold & Layout Shells
|
|
86
|
+
|
|
87
|
+
The `Scaffold` and `DashboardLayout` components provide professional-grade app structures.
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import { Scaffold, Sidebar, Header, Text, StakentButton } from 'fiboui';
|
|
91
|
+
|
|
92
|
+
Scaffold()
|
|
93
|
+
.header(
|
|
94
|
+
Header().height(80).className("px-6 bg-white shadow-sm").children([
|
|
95
|
+
Text("App Title").variant("h2"),
|
|
96
|
+
StakentButton({ text: "Profile", variant: "outline" })
|
|
69
97
|
])
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
)
|
|
99
|
+
.sidebar(
|
|
100
|
+
Sidebar().width(240).children([
|
|
101
|
+
StakentSidebarItem({ label: "Home", active: true, icon: "home" }),
|
|
102
|
+
StakentSidebarItem({ label: "Settings", icon: "settings" })
|
|
103
|
+
])
|
|
104
|
+
)
|
|
105
|
+
.fab(
|
|
106
|
+
Button("+").variant("fab").onPress(() => console.log("Added!"))
|
|
107
|
+
)
|
|
108
|
+
.children([
|
|
109
|
+
Text("Welcome to the main content area.")
|
|
110
|
+
])
|
|
111
|
+
.build()
|
|
72
112
|
```
|
|
73
113
|
|
|
74
|
-
|
|
114
|
+
---
|
|
75
115
|
|
|
76
|
-
|
|
77
|
-
- `Container` - Flexible container
|
|
78
|
-
- `Row` - Horizontal layout
|
|
79
|
-
- `Column` - Vertical layout
|
|
80
|
-
- `Spacer` - Spacing element
|
|
81
|
-
- `Center` - Centering wrapper
|
|
82
|
-
- `Line` - Custom horizontal container
|
|
116
|
+
## 🛒 Full Example: E-commerce Store
|
|
83
117
|
|
|
84
|
-
|
|
85
|
-
- `Text` - Text with typography styles
|
|
86
|
-
- `Image` - Image with SwiftUI-like methods
|
|
118
|
+
Combine **Signals**, **Store**, and **Builders** for a complete reactive application.
|
|
87
119
|
|
|
88
|
-
|
|
89
|
-
|
|
120
|
+
```tsx
|
|
121
|
+
import { signal, computed, createStore, Scaffold, Box, Text, Button, Badge, Row } from 'fiboui';
|
|
122
|
+
|
|
123
|
+
// 1. Global Store
|
|
124
|
+
const appStore = createStore({
|
|
125
|
+
cart: [],
|
|
126
|
+
products: [
|
|
127
|
+
{ id: '1', name: 'MacBook Pro', price: 2499, image: '💻' },
|
|
128
|
+
{ id: '2', name: 'iPhone 15', price: 999, image: '📱' }
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// 2. Reactive Computed Values
|
|
133
|
+
const cartTotal = computed(() => {
|
|
134
|
+
const cart = appStore.getState().cart;
|
|
135
|
+
return cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// 3. UI Component
|
|
139
|
+
export function EcommerceApp() {
|
|
140
|
+
return Scaffold()
|
|
141
|
+
.header(
|
|
142
|
+
Header().children([
|
|
143
|
+
Text('🛒 FiboShop').variant("h2"),
|
|
144
|
+
Row().children([
|
|
145
|
+
Text(`Total: $${cartTotal.value.toFixed(2)}`).bindSignal(cartTotal),
|
|
146
|
+
Badge().text(appStore.getState().cart.length.toString()).observer()
|
|
147
|
+
])
|
|
148
|
+
])
|
|
149
|
+
)
|
|
150
|
+
.children([
|
|
151
|
+
Grid().columns(2).gap("md").children(
|
|
152
|
+
appStore.getState().products.map(product =>
|
|
153
|
+
Card().children([
|
|
154
|
+
Text(product.image).fontSize(40),
|
|
155
|
+
Text(product.name).fontWeight("bold"),
|
|
156
|
+
Button(`Add $${product.price}`).onPress(() => {
|
|
157
|
+
// Update Store & Watch UI React!
|
|
158
|
+
appStore.setState(s => ({ cart: [...s.cart, { ...product, quantity: 1 }] }));
|
|
159
|
+
})
|
|
160
|
+
])
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
])
|
|
164
|
+
.build();
|
|
165
|
+
}
|
|
166
|
+
```
|
|
90
167
|
|
|
91
|
-
|
|
92
|
-
- `Card` - Information card
|
|
93
|
-
- `Banner` - Status banner
|
|
94
|
-
- `List` - Icon-title-subtitle list
|
|
95
|
-
- `Tags` - Badge tags
|
|
96
|
-
- `Box` - Container wrapper
|
|
97
|
-
- `Table` - Data table
|
|
168
|
+
---
|
|
98
169
|
|
|
99
|
-
## License
|
|
170
|
+
## 📄 License
|
|
100
171
|
|
|
101
|
-
MIT
|
|
172
|
+
MIT © 2025 FiboUI
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { Observable, Signal } from './state';
|
|
3
3
|
|
|
4
|
+
export declare function Observer({ children }: {
|
|
5
|
+
children: () => ReactNode;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
4
7
|
export declare const StateContext: import('react').Context<Map<string, any>>;
|
|
5
8
|
export declare function useStateContext(): Map<string, any>;
|
|
6
9
|
interface StateWrapperProps {
|
package/dist/core/builder.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare abstract class FiboBuilder {
|
|
|
15
15
|
protected _signals: Set<Signal<any>>;
|
|
16
16
|
protected _isObserver: boolean;
|
|
17
17
|
id(value: string): this;
|
|
18
|
+
key(value: string | number): this;
|
|
18
19
|
paddingHorizontal(value: string | number): this;
|
|
19
20
|
paddingVertical(value: string | number): this;
|
|
20
21
|
marginHorizontal(value: string | number): this;
|
|
@@ -37,10 +38,12 @@ export declare abstract class FiboBuilder {
|
|
|
37
38
|
css(styles: CSSProperties): this;
|
|
38
39
|
style(style: CSSProperties): this;
|
|
39
40
|
props(props: Record<string, any>): this;
|
|
40
|
-
|
|
41
|
+
protected _childFunction?: () => ReactNode;
|
|
42
|
+
children(children: ReactNode | ReactNode[] | (() => ReactNode)): this;
|
|
41
43
|
protected getClassName(): string;
|
|
42
44
|
protected getStyle(): CSSProperties;
|
|
43
45
|
protected processChildren(): ReactNode[];
|
|
46
|
+
protected getChildFunction(): (() => ReactNode) | undefined;
|
|
44
47
|
abstract build(): ReactElement;
|
|
45
48
|
}
|
|
46
49
|
type StyleBuilder<T> = T & {
|
package/dist/core/effects.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare const createRipple: (event: {
|
|
2
|
+
clientX: number;
|
|
3
|
+
clientY: number;
|
|
4
|
+
}, button: HTMLElement, color?: string) => void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Signal, ComputedSignal, Store, Observable } from './state';
|
|
2
|
+
|
|
3
|
+
export declare function useSignal<T>(signal: Signal<T> | ComputedSignal<T>): T;
|
|
4
|
+
export declare function useStore<T>(store: Store<T>): T;
|
|
5
|
+
export declare function useObservable<T>(obs: Observable<T>): T;
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/state.d.ts
CHANGED
|
@@ -1,37 +1,86 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export type
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export type Listener<T> = (value: T) => void;
|
|
2
|
+
export type Unsubscribe = () => void;
|
|
3
|
+
export interface Subscribable<T> {
|
|
4
|
+
subscribe(listener: Listener<T>): Unsubscribe;
|
|
5
|
+
subscribeEffect(effect: Effect): void;
|
|
6
|
+
unsubscribeEffect(effect: Effect): void;
|
|
7
7
|
}
|
|
8
|
-
export
|
|
9
|
-
|
|
8
|
+
export declare class Effect {
|
|
9
|
+
private fn;
|
|
10
|
+
private dependencies;
|
|
11
|
+
private _onDispose?;
|
|
12
|
+
constructor(fn: () => void);
|
|
13
|
+
run(): void;
|
|
14
|
+
track(dep: Subscribable<any>): void;
|
|
15
|
+
trigger(): void;
|
|
16
|
+
cleanup(): void;
|
|
17
|
+
dispose(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class Tracker {
|
|
20
|
+
private _onInvalidate;
|
|
21
|
+
private dependencies;
|
|
22
|
+
constructor(_onInvalidate: () => void);
|
|
23
|
+
execute<T>(fn: () => T): T;
|
|
24
|
+
track(dep: Subscribable<any>): void;
|
|
25
|
+
trigger(): void;
|
|
26
|
+
cleanup(): void;
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}
|
|
29
|
+
export declare class Signal<T> implements Subscribable<T> {
|
|
30
|
+
private _value;
|
|
31
|
+
private listeners;
|
|
32
|
+
private effects;
|
|
33
|
+
constructor(_value: T);
|
|
34
|
+
get value(): T;
|
|
35
|
+
set value(newValue: T);
|
|
36
|
+
subscribe(listener: Listener<T>): Unsubscribe;
|
|
37
|
+
subscribeEffect(effect: Effect): void;
|
|
38
|
+
unsubscribeEffect(effect: Effect): void;
|
|
39
|
+
private notify;
|
|
10
40
|
}
|
|
11
|
-
type EffectCleanup = void | (() => void);
|
|
12
41
|
export declare function signal<T>(initialValue: T): Signal<T>;
|
|
42
|
+
export declare class ComputedSignal<T> implements Subscribable<T> {
|
|
43
|
+
private fn;
|
|
44
|
+
private listeners;
|
|
45
|
+
private effects;
|
|
46
|
+
private _value;
|
|
47
|
+
private _dirty;
|
|
48
|
+
private internalEffect;
|
|
49
|
+
constructor(fn: () => T);
|
|
50
|
+
get value(): T;
|
|
51
|
+
subscribe(listener: Listener<T>): Unsubscribe;
|
|
52
|
+
subscribeEffect(effect: Effect): void;
|
|
53
|
+
unsubscribeEffect(effect: Effect): void;
|
|
54
|
+
private notify;
|
|
55
|
+
}
|
|
13
56
|
export declare function computed<T>(fn: () => T): ComputedSignal<T>;
|
|
14
|
-
export declare
|
|
15
|
-
|
|
57
|
+
export declare class Observable<T> implements Subscribable<T> {
|
|
58
|
+
private _value;
|
|
59
|
+
private listeners;
|
|
60
|
+
private effects;
|
|
61
|
+
constructor(_value: T);
|
|
16
62
|
get(): T;
|
|
17
|
-
set(
|
|
18
|
-
subscribe(listener:
|
|
63
|
+
set(newValue: T): void;
|
|
64
|
+
subscribe(listener: Listener<T>): Unsubscribe;
|
|
65
|
+
subscribeEffect(effect: Effect): void;
|
|
66
|
+
unsubscribeEffect(effect: Effect): void;
|
|
67
|
+
private notify;
|
|
19
68
|
}
|
|
20
69
|
export declare function observable<T>(initialValue: T): Observable<T>;
|
|
21
|
-
export interface Store<T> {
|
|
70
|
+
export interface Store<T> extends Subscribable<T> {
|
|
22
71
|
getState(): T;
|
|
23
|
-
setState(
|
|
24
|
-
subscribe(listener: (state: T) => void): () => void;
|
|
72
|
+
setState(fn: Partial<T> | ((state: T) => Partial<T>)): void;
|
|
25
73
|
}
|
|
26
|
-
export declare
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
74
|
+
export declare class StoreImpl<T> implements Store<T> {
|
|
75
|
+
private state;
|
|
76
|
+
private listeners;
|
|
77
|
+
private effects;
|
|
78
|
+
constructor(state: T);
|
|
79
|
+
getState(): T;
|
|
80
|
+
setState(partial: Partial<T> | ((state: T) => Partial<T>)): void;
|
|
81
|
+
subscribe(listener: Listener<T>): Unsubscribe;
|
|
82
|
+
subscribeEffect(effect: Effect): void;
|
|
83
|
+
unsubscribeEffect(effect: Effect): void;
|
|
84
|
+
private notify;
|
|
33
85
|
}
|
|
34
|
-
export declare function
|
|
35
|
-
export declare function getProvider<T>(key: string): T | undefined;
|
|
36
|
-
export declare function clearProviders(): void;
|
|
37
|
-
export {};
|
|
86
|
+
export declare function createStore<T>(initialState: T): Store<T>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const c = (i, t, s = "rgba(255, 255, 255, 0.3)") => {
|
|
2
|
+
if (!t) return;
|
|
3
|
+
const e = document.createElement("span"), l = Math.max(t.clientWidth, t.clientHeight), n = l / 2, r = t.getBoundingClientRect();
|
|
4
|
+
e.style.width = e.style.height = `${l}px`, e.style.left = `${i.clientX - r.left - n}px`, e.style.top = `${i.clientY - r.top - n}px`, e.style.position = "absolute", e.style.borderRadius = "50%", e.style.transform = "scale(0)", e.style.animation = "fibo-ripple 600ms linear", e.style.backgroundColor = s, e.style.pointerEvents = "none", (t.querySelector(".fibo-ripple-container") || t).appendChild(e), setTimeout(() => {
|
|
5
|
+
e.remove();
|
|
6
|
+
}, 600);
|
|
7
|
+
};
|
|
8
|
+
export {
|
|
9
|
+
c as createRipple
|
|
10
|
+
};
|