@diffsome/react 1.1.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 +353 -0
- package/dist/index.d.mts +546 -0
- package/dist/index.d.ts +546 -0
- package/dist/index.js +2340 -0
- package/dist/index.mjs +2255 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# @diffsome/react
|
|
2
|
+
|
|
3
|
+
Headless React hooks and providers for Diffsome SDK. Build any e-commerce or CMS frontend with your own UI components.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @diffsome/react @diffsome/sdk
|
|
9
|
+
# or
|
|
10
|
+
yarn add @diffsome/react @diffsome/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { DiffsomeProvider, useAuth, useCart, useProducts } from '@diffsome/react';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return (
|
|
20
|
+
<DiffsomeProvider
|
|
21
|
+
config={{
|
|
22
|
+
tenantId: 'my-store',
|
|
23
|
+
apiKey: 'pky_your_api_key',
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
<Shop />
|
|
27
|
+
</DiffsomeProvider>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function Shop() {
|
|
32
|
+
const { user, login, logout } = useAuth();
|
|
33
|
+
const { items, addToCart, total } = useCart();
|
|
34
|
+
const { products, loading } = useProducts();
|
|
35
|
+
|
|
36
|
+
if (loading) return <div>Loading...</div>;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div>
|
|
40
|
+
{user ? (
|
|
41
|
+
<p>Welcome, {user.name}! <button onClick={logout}>Logout</button></p>
|
|
42
|
+
) : (
|
|
43
|
+
<button onClick={() => login({ email: '...', password: '...' })}>Login</button>
|
|
44
|
+
)}
|
|
45
|
+
|
|
46
|
+
<h2>Products</h2>
|
|
47
|
+
{products.map(product => (
|
|
48
|
+
<div key={product.id}>
|
|
49
|
+
<h3>{product.name}</h3>
|
|
50
|
+
<p>${product.sale_price}</p>
|
|
51
|
+
<button onClick={() => addToCart(product.id)}>Add to Cart</button>
|
|
52
|
+
</div>
|
|
53
|
+
))}
|
|
54
|
+
|
|
55
|
+
<h2>Cart ({items.length} items)</h2>
|
|
56
|
+
<p>Total: ${total}</p>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Available Hooks
|
|
63
|
+
|
|
64
|
+
### Authentication
|
|
65
|
+
- `useAuth()` - Login, register, logout, profile management
|
|
66
|
+
- `useSocialAuth()` - Social login (Google, Kakao, Naver, etc.)
|
|
67
|
+
|
|
68
|
+
### E-commerce
|
|
69
|
+
- `useCart()` - Cart management (add, update, remove items)
|
|
70
|
+
- `useWishlist()` - Wishlist management
|
|
71
|
+
- `useProducts()` - Product listing with pagination
|
|
72
|
+
- `useProduct(slug)` - Single product details
|
|
73
|
+
- `useCategories()` - Product categories
|
|
74
|
+
- `useFeaturedProducts()` - Featured products
|
|
75
|
+
- `useOrders()` - Order history
|
|
76
|
+
- `useOrder(id)` - Single order details
|
|
77
|
+
- `useCreateOrder()` - Create new order
|
|
78
|
+
|
|
79
|
+
### Payment
|
|
80
|
+
- `usePaymentStatus()` - Check available payment methods (Toss, Stripe)
|
|
81
|
+
- `useTossPayment()` - Toss Payments (Korea)
|
|
82
|
+
- `useStripePayment()` - Stripe Payments (Global)
|
|
83
|
+
- `useCoupons()` - User's available coupons
|
|
84
|
+
- `useValidateCoupon()` - Validate coupon code
|
|
85
|
+
|
|
86
|
+
### Subscriptions
|
|
87
|
+
- `useSubscriptions()` - User's subscriptions
|
|
88
|
+
- `useSubscription(id)` - Single subscription with cancel/pause/resume
|
|
89
|
+
- `useCreateSubscription()` - Create subscription via Stripe
|
|
90
|
+
|
|
91
|
+
### Digital Downloads
|
|
92
|
+
- `useDownloads()` - User's digital download links
|
|
93
|
+
- `useOrderDownloads(orderNumber)` - Downloads for specific order
|
|
94
|
+
|
|
95
|
+
### Reviews
|
|
96
|
+
- `useProductReviews(slug)` - Product reviews
|
|
97
|
+
- `useMyReviews()` - User's reviews
|
|
98
|
+
- `useCanReview(slug)` - Check review eligibility
|
|
99
|
+
- `useCreateReview()` - Create product review
|
|
100
|
+
|
|
101
|
+
### Content
|
|
102
|
+
- `useBlog()` - Blog posts with pagination
|
|
103
|
+
- `useBlogPost(slug)` - Single blog post
|
|
104
|
+
- `useBlogCategories()` - Blog categories
|
|
105
|
+
- `useBoards()` - Board listing
|
|
106
|
+
- `useBoard(slug)` - Single board
|
|
107
|
+
- `useBoardPosts(slug)` - Board posts
|
|
108
|
+
- `useBoardPost(id)` - Single board post
|
|
109
|
+
- `useCreateBoardPost()` - Create board post
|
|
110
|
+
- `useComments({ type, target })` - Comments for board/blog/standalone
|
|
111
|
+
- `useForm(slug)` - Form with submission
|
|
112
|
+
|
|
113
|
+
### Reservations
|
|
114
|
+
- `useReservationServices()` - Available services
|
|
115
|
+
- `useReservationStaffs()` - Staff members
|
|
116
|
+
- `useAvailableSlots(serviceId, date)` - Time slots
|
|
117
|
+
- `useMyReservations()` - User's reservations
|
|
118
|
+
- `useCreateReservation()` - Create reservation
|
|
119
|
+
- `useReservationSettings()` - Reservation settings
|
|
120
|
+
|
|
121
|
+
### Media
|
|
122
|
+
- `useMedia()` - File upload and management
|
|
123
|
+
|
|
124
|
+
### Custom Entities (Dynamic Data)
|
|
125
|
+
- `useEntities()` - List all entity definitions
|
|
126
|
+
- `useEntity(slug)` - Single entity with schema
|
|
127
|
+
- `useEntityRecords(slug)` - CRUD for entity records
|
|
128
|
+
- `useEntityRecord(slug, id)` - Single record
|
|
129
|
+
- `useTypedEntity<T>(slug)` - Typed entity accessor
|
|
130
|
+
|
|
131
|
+
## Hook Examples
|
|
132
|
+
|
|
133
|
+
### useAuth
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
function LoginForm() {
|
|
137
|
+
const { user, login, logout, loading, error } = useAuth();
|
|
138
|
+
const [email, setEmail] = useState('');
|
|
139
|
+
const [password, setPassword] = useState('');
|
|
140
|
+
|
|
141
|
+
const handleSubmit = async (e) => {
|
|
142
|
+
e.preventDefault();
|
|
143
|
+
await login({ email, password });
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
if (user) {
|
|
147
|
+
return (
|
|
148
|
+
<div>
|
|
149
|
+
<p>Welcome, {user.name}</p>
|
|
150
|
+
<button onClick={logout}>Logout</button>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<form onSubmit={handleSubmit}>
|
|
157
|
+
<input value={email} onChange={(e) => setEmail(e.target.value)} />
|
|
158
|
+
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
|
|
159
|
+
<button disabled={loading}>Login</button>
|
|
160
|
+
{error && <p>{error.message}</p>}
|
|
161
|
+
</form>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### useCart
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
function Cart() {
|
|
170
|
+
const { items, total, updateItem, removeItem, clearCart } = useCart();
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div>
|
|
174
|
+
{items.map(item => (
|
|
175
|
+
<div key={item.id}>
|
|
176
|
+
<span>{item.product_name}</span>
|
|
177
|
+
<input
|
|
178
|
+
type="number"
|
|
179
|
+
value={item.quantity}
|
|
180
|
+
onChange={(e) => updateItem(item.id, parseInt(e.target.value))}
|
|
181
|
+
/>
|
|
182
|
+
<button onClick={() => removeItem(item.id)}>Remove</button>
|
|
183
|
+
</div>
|
|
184
|
+
))}
|
|
185
|
+
<p>Total: ${total}</p>
|
|
186
|
+
<button onClick={clearCart}>Clear Cart</button>
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### useWishlist
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
function WishlistButton({ productId }) {
|
|
196
|
+
const { isInWishlist, toggleWishlist } = useWishlist();
|
|
197
|
+
const inWishlist = isInWishlist(productId);
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<button onClick={() => toggleWishlist(productId)}>
|
|
201
|
+
{inWishlist ? '❤️' : '🤍'}
|
|
202
|
+
</button>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### useStripePayment
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
function CheckoutButton({ orderNumber }) {
|
|
211
|
+
const { createCheckout, loading } = useStripePayment();
|
|
212
|
+
|
|
213
|
+
const handleCheckout = async () => {
|
|
214
|
+
const { checkout_url } = await createCheckout(
|
|
215
|
+
orderNumber,
|
|
216
|
+
`${window.location.origin}/checkout/success`,
|
|
217
|
+
`${window.location.origin}/checkout/cancel`
|
|
218
|
+
);
|
|
219
|
+
window.location.href = checkout_url;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<button onClick={handleCheckout} disabled={loading}>
|
|
224
|
+
Pay with Stripe
|
|
225
|
+
</button>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### useComments
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
function Comments({ postId }) {
|
|
234
|
+
const { comments, createComment, likeComment, loading } = useComments({
|
|
235
|
+
type: 'board',
|
|
236
|
+
target: postId,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const handleSubmit = async (content) => {
|
|
240
|
+
await createComment({ content });
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<div>
|
|
245
|
+
{comments.map(comment => (
|
|
246
|
+
<div key={comment.id}>
|
|
247
|
+
<p>{comment.content}</p>
|
|
248
|
+
<button onClick={() => likeComment(comment.id)}>
|
|
249
|
+
Like ({comment.likes})
|
|
250
|
+
</button>
|
|
251
|
+
</div>
|
|
252
|
+
))}
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### useEntityRecords (Custom Entities)
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
// Dynamic CRM example
|
|
262
|
+
function CustomerList() {
|
|
263
|
+
const { records, createRecord, deleteRecord, loading } = useEntityRecords('customers');
|
|
264
|
+
|
|
265
|
+
const addCustomer = async () => {
|
|
266
|
+
await createRecord({
|
|
267
|
+
company: 'ACME Corp',
|
|
268
|
+
email: 'contact@acme.com',
|
|
269
|
+
tier: 'vip',
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<div>
|
|
275
|
+
{records.map(customer => (
|
|
276
|
+
<div key={customer.id}>
|
|
277
|
+
<span>{customer.data.company}</span>
|
|
278
|
+
<button onClick={() => deleteRecord(customer.id)}>Delete</button>
|
|
279
|
+
</div>
|
|
280
|
+
))}
|
|
281
|
+
<button onClick={addCustomer}>Add Customer</button>
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// With TypeScript
|
|
287
|
+
interface Customer {
|
|
288
|
+
company: string;
|
|
289
|
+
email: string;
|
|
290
|
+
tier: 'standard' | 'vip';
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function TypedCustomerList() {
|
|
294
|
+
const customers = useTypedEntity<Customer>('customers');
|
|
295
|
+
// customers.useRecords() returns typed records
|
|
296
|
+
// customers.create({ company: '...' }) has type checking
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### useMedia
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
function FileUploader() {
|
|
304
|
+
const { upload, uploading, uploadProgress } = useMedia();
|
|
305
|
+
|
|
306
|
+
const handleFileChange = async (e) => {
|
|
307
|
+
const file = e.target.files[0];
|
|
308
|
+
if (file) {
|
|
309
|
+
const media = await upload(file);
|
|
310
|
+
console.log('Uploaded:', media.url);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
return (
|
|
315
|
+
<div>
|
|
316
|
+
<input type="file" onChange={handleFileChange} disabled={uploading} />
|
|
317
|
+
{uploading && <progress value={uploadProgress} max={100} />}
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Low-level Access
|
|
324
|
+
|
|
325
|
+
Use `useClient()` to access the SDK directly:
|
|
326
|
+
|
|
327
|
+
```tsx
|
|
328
|
+
import { useClient } from '@diffsome/react';
|
|
329
|
+
|
|
330
|
+
function CustomComponent() {
|
|
331
|
+
const client = useClient();
|
|
332
|
+
|
|
333
|
+
const handleCustomAction = async () => {
|
|
334
|
+
// Direct SDK access
|
|
335
|
+
const result = await client.shop.validateCoupon('SAVE10', 5000);
|
|
336
|
+
console.log(result);
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
return <button onClick={handleCustomAction}>Validate Coupon</button>;
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## TypeScript
|
|
344
|
+
|
|
345
|
+
All types are re-exported from `@diffsome/sdk`:
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
import type { Product, Cart, Order, Member, CustomEntity, EntityRecord } from '@diffsome/react';
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## License
|
|
352
|
+
|
|
353
|
+
MIT
|