wini-web-components 8.4.97 → 8.4.98

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 (2) hide show
  1. package/README.md +903 -63
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,73 +1,913 @@
1
1
  # wini-web-components
2
2
 
3
- A modern, lightweight, and highly customizable UI component library for ReactJS projects. Built with TSX, JSX, and CSS, `wini-web-components` provides a collection of reusable components to help you create responsive, beautiful, and user-friendly interfaces with ease. Whether you're building a small app or a large-scale project, this library offers the flexibility and tools you need to speed up your development process.
3
+ A modern, lightweight React TypeScript UI component library with 35+ ready-to-use components, responsive layout utilities, design token theming, and optional Wini backend integration for dynamic form/table/page rendering.
4
4
 
5
- ## Why Choose wini-web-components?
5
+ [![npm version](https://img.shields.io/npm/v/wini-web-components)](https://www.npmjs.com/package/wini-web-components)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
7
 
7
- - **Ready-to-Use Components**: A wide range of pre-built UI components for quick integration.
8
- - **Responsive Design**: Built-in CSS classes for seamless responsiveness across devices, from mobile to extra-large screens.
9
- - **Customizable**: Easily style and configure components to match your project's design.
10
- - **Lightweight**: Minimal overhead to keep your app fast and efficient.
11
- - **TypeScript Support**: Fully typed with TSX for a better developer experience.
8
+ ---
12
9
 
13
- ## Installation
10
+ ## Table of Contents
11
+
12
+ - [Installation](#installation)
13
+ - [Setup: Add Global Styles](#setup-add-global-styles)
14
+ - [Setup: Wrap Your App with WiniProvider](#setup-wrap-your-app-with-winiprovider)
15
+ - [Layout System](#layout-system)
16
+ - [Components](#components)
17
+ - [Button](#button)
18
+ - [Winicon](#winicon)
19
+ - [TextField](#textfield)
20
+ - [TextArea](#textarea)
21
+ - [Select1](#select1)
22
+ - [Checkbox](#checkbox)
23
+ - [Switch](#switch)
24
+ - [RadioButton](#radiobutton)
25
+ - [DateTimePicker](#datetimepicker)
26
+ - [NumberPicker](#numberpicker)
27
+ - [Slider](#slider)
28
+ - [Rating](#rating)
29
+ - [InputOtp](#inputotp)
30
+ - [ColorPicker](#colorpicker)
31
+ - [SelectMultiple](#selectmultiple)
32
+ - [Tag](#tag)
33
+ - [Pagination](#pagination)
34
+ - [InfiniteScroll](#infinitescroll)
35
+ - [Dialog](#dialog)
36
+ - [Popup](#popup)
37
+ - [ToastMessage](#toastmessage)
38
+ - [ProgressBar](#progressbar)
39
+ - [ProgressCircle](#progresscircle)
40
+ - [Calendar](#calendar)
41
+ - [Carousel](#carousel)
42
+ - [VideoPlayer / AudioPlayer / IframePlayer](#videoplayer--audioplayer--iframeplayer)
43
+ - [ImportFile / UploadFiles](#importfile--uploadfiles)
44
+ - [CustomCkEditor5](#customckeditor5)
45
+ - [WiniEditor](#winieditor)
46
+ - [IconPicker](#iconpicker)
47
+ - [Backend-Driven Modules](#backend-driven-modules)
48
+ - [PageById](#pagebyid)
49
+ - [PageByUrl](#pagebyurl)
50
+ - [FormById](#formbyid)
51
+ - [CardById](#cardbyid)
52
+ - [ViewById](#viewbyid)
53
+ - [Responsive Grid Classes](#responsive-grid-classes)
54
+ - [Design Tokens & Theming](#design-tokens--theming)
14
55
 
15
- Install the package via npm:
56
+ ---
16
57
 
58
+ ## Installation
17
59
 
60
+ ```bash
18
61
  npm install wini-web-components
62
+ ```
63
+
64
+ > **Peer dependencies** — install these in your project if not already present:
65
+ > ```bash
66
+ > npm install react react-dom react-router-dom
67
+ > ```
68
+ > For CKEditor support: `npm install ckeditor5 @ckeditor/ckeditor5-react`
69
+
70
+ ---
71
+
72
+ ## Setup: Add Global Styles
73
+
74
+ Add these imports at the top of your root CSS file (e.g. `App.css` or `index.css`):
75
+
76
+ ```css
77
+ @import url(https://cdn.jsdelivr.net/gh/WiniGit/web-component@latest/src/skin/root.css);
78
+ @import url(https://cdn.jsdelivr.net/gh/WiniGit/web-component@latest/src/skin/typography.css);
79
+ @import url(https://cdn.jsdelivr.net/gh/WiniGit/web-component@latest/src/skin/layout.css);
80
+ ```
81
+
82
+ These provide:
83
+ - **`root.css`** — CSS design token variables (colors, borders, shadows)
84
+ - **`typography.css`** — text utility classes (`heading-1` → `heading-8`, `body-1` → `body-3`, etc.)
85
+ - **`layout.css`** — `row`, `col`, and responsive grid classes
86
+
87
+ ---
88
+
89
+ ## Setup: Wrap Your App with WiniProvider
90
+
91
+ `WiniProvider` is the root provider. It sets up routing, toasts, dialogs, auth token handling, and optionally loads design tokens and i18n from a Wini backend.
92
+
93
+ ```tsx
94
+ // main.tsx
95
+ import WiniProvider from 'wini-web-components'
96
+
97
+ ReactDOM.createRoot(document.getElementById('root')!).render(
98
+ <WiniProvider
99
+ pid="your-project-id"
100
+ url="https://your-wini-api.com/"
101
+ fileUrl="https://your-file-server.com/"
102
+ imgUrlId="https://your-cdn.com/"
103
+ theme="light" // "light" | "dark"
104
+ loadResources={true} // set false to skip backend token/i18n loading
105
+ >
106
+ <Route path="/" element={<HomePage />} />
107
+ <Route path="/about" element={<AboutPage />} />
108
+ </WiniProvider>
109
+ )
110
+ ```
111
+
112
+ > **Note:** `WiniProvider` wraps `BrowserRouter` internally — do **not** add another `BrowserRouter` in your app.
113
+
114
+ ### Access Global Context
115
+
116
+ ```tsx
117
+ import { useWiniContext } from 'wini-web-components'
118
+
119
+ function MyComponent() {
120
+ const { theme, setTheme, userData, setUserData } = useWiniContext()
121
+ return <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Toggle theme</button>
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Layout System
128
+
129
+ Use `row` and `col` classes for flex layouts. These are available globally after importing the skin CSS.
130
+
131
+ ```tsx
132
+ // Horizontal layout (flex-direction: row, align-items: center)
133
+ <div className="row" style={{ gap: 12 }}>
134
+ <span>Left</span>
135
+ <span className="remain">This stretches to fill remaining space</span>
136
+ <span>Right</span>
137
+ </div>
138
+
139
+ // Vertical layout (flex-direction: column)
140
+ <div className="col" style={{ gap: 8 }}>
141
+ <span>Top</span>
142
+ <span>Bottom</span>
143
+ </div>
144
+ ```
145
+
146
+ > `remain` inside a `row` or `col` expands to fill available space (`flex: 1`).
147
+
148
+ ---
149
+
150
+ ## Components
151
+
152
+ ### Button
153
+
154
+ A versatile button supporting sizes, color variants, icons, links, tooltips, and keyboard `Enter` on submit type.
155
+
156
+ ```tsx
157
+ import { Button, Winicon } from 'wini-web-components'
158
+
159
+ // Basic
160
+ <Button label="Click me" onClick={() => alert('clicked!')} />
161
+
162
+ // Size variants (default: size32)
163
+ <Button label="Large" className="size48 button-primary" onClick={...} />
164
+
165
+ // As a link
166
+ <Button label="Go to docs" linkTo="https://example.com" target="_blank" className="size40 button-neutral" />
167
+
168
+ // With prefix icon
169
+ <Button
170
+ label="Save"
171
+ prefix={<Winicon src="outline/files/save-2" size={16} />}
172
+ className="size40 button-primary"
173
+ onClick={...}
174
+ />
175
+
176
+ // With tooltip
177
+ <Button label="Info" tooltip={{ message: 'More details', position: 'top' }} />
178
+
179
+ // Submit type — also triggers on Enter key
180
+ <Button label="Submit" type="submit" className="size40 button-primary" onClick={...} />
181
+ ```
182
+
183
+ **Size classes:** `size24` `size32`*(default)* `size40` `size48` `size56` `size64`
184
+
185
+ **Color classes:** `button-primary` `button-grey` `button-neutral` `button-black` `button-white` `button-infor` `button-warning` `button-error` `button-success` `button-infor-main` `button-warning-main` `button-error-main` `button-success-main`
186
+
187
+ > `SimpleButton` is a variant that auto-disables itself during the async `onClick` to prevent double-clicks.
188
+
189
+ ---
190
+
191
+ ### Winicon
192
+
193
+ SVG icon component loaded from the [WiniGit icon library CDN](https://github.com/WiniGit/icon-library). Icons are cached in the browser after first load.
194
+
195
+ ```tsx
196
+ import { Winicon } from 'wini-web-components'
197
+
198
+ <Winicon src="outline/user/user" size={24} color="#287CF0" />
199
+ <Winicon src="fill/actions/trash" size={20} onClick={() => handleDelete()} className="icon-button" />
200
+
201
+ // With tooltip
202
+ <Winicon src="outline/essential/info-circle" size={20} tooltip={{ message: 'Help', position: 'bottom' }} />
203
+ ```
204
+
205
+ **Size classes:** `size24` `size32` `size40` `size48` `size56` `size64`
206
+ **Style classes:** `icon-button` (adds hover/click interactivity styles), `light`
207
+
208
+ ---
209
+
210
+ ### TextField
211
+
212
+ Styled text input with optional prefix/suffix slots, helper text, and `react-hook-form` support.
213
+
214
+ ```tsx
215
+ import { TextField } from 'wini-web-components'
216
+
217
+ // Basic
218
+ <TextField placeholder="Enter name" onChange={(e) => setName(e.target.value)} />
219
+
220
+ // With prefix icon and helper text
221
+ <TextField
222
+ prefix={<Winicon src="outline/user/user" size={16} />}
223
+ placeholder="Email"
224
+ type="email"
225
+ helperText="Invalid email" // shown below the field in red
226
+ className="size40 body-3"
227
+ />
228
+
229
+ // With react-hook-form
230
+ const { register } = useForm()
231
+ <TextField placeholder="Username" register={register('username', { required: true })} />
232
+ ```
233
+
234
+ **Size classes:** `size24` `size32` `size40`*(default)* `size48`
235
+
236
+ ---
237
+
238
+ ### TextArea
239
+
240
+ Multi-line text input.
241
+
242
+ ```tsx
243
+ import { TextArea } from 'wini-web-components'
244
+
245
+ <TextArea placeholder="Write something..." onChange={(e) => setText(e.target.value)} />
246
+ ```
247
+
248
+ ---
249
+
250
+ ### Select1
251
+
252
+ Single-value dropdown. Supports static options, async lazy-loading, hierarchical (parent/child) options, and custom render.
253
+
254
+ ```tsx
255
+ import { Select1 } from 'wini-web-components'
256
+
257
+ const options = [
258
+ { id: '1', name: 'Option A' },
259
+ { id: '2', name: 'Option B' },
260
+ { id: '3', name: 'Option C', disabled: true },
261
+ ]
262
+
263
+ // Static options
264
+ <Select1
265
+ value={selected}
266
+ options={options}
267
+ placeholder="Choose one"
268
+ onChange={(item) => setSelected(item?.id)}
269
+ />
270
+
271
+ // Async options (loaded on open / search)
272
+ <Select1
273
+ options={[]}
274
+ getOptions={async ({ length, search }) => {
275
+ const res = await fetchItems({ page: Math.floor(length / 10) + 1, search })
276
+ return { data: res.items, totalCount: res.total }
277
+ }}
278
+ onChange={(item) => setSelected(item?.id)}
279
+ />
280
+ ```
281
+
282
+ ---
283
+
284
+ ### Checkbox
285
+
286
+ ```tsx
287
+ import { Checkbox } from 'wini-web-components'
288
+
289
+ <Checkbox value={isChecked} onChange={(val) => setIsChecked(val)} />
290
+ <Checkbox value={null} /> {/* null = indeterminate state */}
291
+ ```
292
+
293
+ ---
294
+
295
+ ### Switch
296
+
297
+ Toggle switch with customizable colors and size.
298
+
299
+ ```tsx
300
+ import { Switch } from 'wini-web-components'
301
+
302
+ <Switch value={isOn} onChange={(val) => setIsOn(val)} />
303
+ <Switch value={isOn} size="2.4rem" onBackground="#287CF0" offBackground="#D7D7DB" onChange={...} />
304
+ ```
305
+
306
+ ---
307
+
308
+ ### RadioButton
309
+
310
+ ```tsx
311
+ import { RadioButton } from 'wini-web-components'
312
+
313
+ <RadioButton value={selected === 'a'} onChange={() => setSelected('a')} label="Option A" />
314
+ <RadioButton value={selected === 'b'} onChange={() => setSelected('b')} label="Option B" />
315
+ ```
316
+
317
+ ---
318
+
319
+ ### DateTimePicker
320
+
321
+ Date and/or time picker.
322
+
323
+ ```tsx
324
+ import { DateTimePicker } from 'wini-web-components'
325
+
326
+ <DateTimePicker value={date} onChange={(val) => setDate(val)} placeholder="Pick a date" />
327
+ ```
328
+
329
+ ---
330
+
331
+ ### NumberPicker
332
+
333
+ Numeric input with increment/decrement controls.
334
+
335
+ ```tsx
336
+ import { NumberPicker } from 'wini-web-components'
337
+
338
+ <NumberPicker value={count} onChange={(val) => setCount(val)} min={0} max={100} />
339
+ ```
340
+
341
+ ---
342
+
343
+ ### Slider
344
+
345
+ Range slider input.
346
+
347
+ ```tsx
348
+ import { Slider } from 'wini-web-components'
349
+
350
+ <Slider value={volume} min={0} max={100} onChange={(val) => setVolume(val)} />
351
+ ```
352
+
353
+ ---
354
+
355
+ ### Rating
356
+
357
+ Star rating input.
358
+
359
+ ```tsx
360
+ import { Rating } from 'wini-web-components'
361
+
362
+ <Rating value={3} onChange={(val) => setRating(val)} />
363
+ ```
364
+
365
+ ---
366
+
367
+ ### InputOtp
368
+
369
+ OTP / PIN code input with configurable digit count.
370
+
371
+ ```tsx
372
+ import { InputOtp } from 'wini-web-components'
373
+
374
+ <InputOtp length={6} onComplete={(code) => verifyOtp(code)} />
375
+ ```
376
+
377
+ ---
378
+
379
+ ### ColorPicker
380
+
381
+ Hex/RGBA color picker input.
382
+
383
+ ```tsx
384
+ import { ColorPicker } from 'wini-web-components'
385
+
386
+ <ColorPicker value={color} onChange={(hex) => setColor(hex)} />
387
+ ```
388
+
389
+ ---
390
+
391
+ ### SelectMultiple
392
+
393
+ Multi-value dropdown with tag display.
394
+
395
+ ```tsx
396
+ import { SelectMultiple } from 'wini-web-components'
397
+
398
+ <SelectMultiple
399
+ value={['1', '2']}
400
+ options={[{ id: '1', name: 'React' }, { id: '2', name: 'TypeScript' }]}
401
+ onChange={(items) => setSelected(items.map(i => i.id))}
402
+ />
403
+ ```
404
+
405
+ ---
406
+
407
+ ### Tag
408
+
409
+ Small label/badge component with color support.
410
+
411
+ ```tsx
412
+ import { Tag } from 'wini-web-components'
413
+
414
+ <Tag>Active</Tag>
415
+ <Tag style={{ backgroundColor: '#B7D3FA', color: '#287CF0' }}>Info</Tag>
416
+ ```
417
+
418
+ ---
419
+
420
+ ### Pagination
421
+
422
+ Page navigation component.
423
+
424
+ ```tsx
425
+ import { Pagination } from 'wini-web-components'
426
+
427
+ <Pagination
428
+ currentPage={page}
429
+ total={totalItems}
430
+ pageSize={20}
431
+ onChange={(newPage) => setPage(newPage)}
432
+ />
433
+ ```
434
+
435
+ ---
436
+
437
+ ### InfiniteScroll
438
+
439
+ Trigger a callback when the user scrolls to the bottom of a container.
440
+
441
+ ```tsx
442
+ import { InfiniteScroll } from 'wini-web-components'
443
+
444
+ <InfiniteScroll onLoadMore={() => fetchNextPage()} isLoading={loading} hasMore={hasMore}>
445
+ {items.map(item => <div key={item.id}>{item.name}</div>)}
446
+ </InfiniteScroll>
447
+ ```
448
+
449
+ ---
450
+
451
+ ### Dialog
452
+
453
+ A global imperative dialog (confirm/alert modal). Rendered by `WiniProvider` — no extra setup needed.
454
+
455
+ ```tsx
456
+ import { showDialog, DialogAlignment, ComponentStatus } from 'wini-web-components'
457
+
458
+ showDialog({
459
+ title: 'Delete item?',
460
+ content: 'This action cannot be undone.',
461
+ status: ComponentStatus.ERROR,
462
+ alignment: DialogAlignment.center,
463
+ onSubmit: () => handleDelete(),
464
+ submitTitle: 'Delete',
465
+ cancelTitle: 'Cancel',
466
+ })
467
+ ```
468
+
469
+ **Status options:** `ComponentStatus.INFOR` `ComponentStatus.WARNING` `ComponentStatus.ERROR` `ComponentStatus.SUCCESS`
470
+
471
+ ---
472
+
473
+ ### Popup
474
+
475
+ A flexible fullscreen/overlay modal managed via ref.
476
+
477
+ ```tsx
478
+ import { Popup, showPopup, closePopup } from 'wini-web-components'
479
+ import { useRef } from 'react'
480
+
481
+ const popupRef = useRef<Popup>()
482
+
483
+ // Trigger open
484
+ showPopup({
485
+ ref: popupRef,
486
+ heading: <h3>My Popup</h3>,
487
+ body: <p>Custom content here</p>,
488
+ footer: <Button label="Close" onClick={() => closePopup(popupRef)} />,
489
+ clickOverlayClosePopup: true,
490
+ })
491
+
492
+ // Place once in your JSX
493
+ <Popup ref={popupRef} />
494
+ ```
495
+
496
+ ---
497
+
498
+ ### ToastMessage
499
+
500
+ Imperative toast notifications. Rendered by `WiniProvider` — no extra setup needed.
501
+
502
+ ```tsx
503
+ import { ToastMessage } from 'wini-web-components'
504
+
505
+ ToastMessage.success('Saved successfully!')
506
+ ToastMessage.errors('Something went wrong.')
507
+ ToastMessage.warn('Check your input.')
508
+ ToastMessage.infor('New update available.')
509
+ ```
510
+
511
+ ---
512
+
513
+ ### ProgressBar
514
+
515
+ ```tsx
516
+ import { ProgressBar } from 'wini-web-components'
517
+
518
+ <ProgressBar value={72} max={100} />
519
+ ```
520
+
521
+ ---
522
+
523
+ ### ProgressCircle
524
+
525
+ ```tsx
526
+ import { ProgressCircle } from 'wini-web-components'
527
+
528
+ <ProgressCircle value={72} max={100} />
529
+ ```
530
+
531
+ ---
532
+
533
+ ### Calendar
534
+
535
+ Standalone date calendar view.
536
+
537
+ ```tsx
538
+ import { Calendar } from 'wini-web-components'
539
+
540
+ <Calendar value={date} onChange={(val) => setDate(val)} />
541
+ ```
542
+
543
+ ---
544
+
545
+ ### Carousel
546
+
547
+ Image/content slideshow powered by `react-awesome-slider`.
548
+
549
+ ```tsx
550
+ import { Carousel } from 'wini-web-components'
551
+
552
+ <Carousel>
553
+ <div data-src="/image1.jpg" />
554
+ <div data-src="/image2.jpg" />
555
+ </Carousel>
556
+ ```
557
+
558
+ ---
559
+
560
+ ### VideoPlayer / AudioPlayer / IframePlayer
561
+
562
+ Media player components for video, audio, and embedded iframes.
563
+
564
+ ```tsx
565
+ import { VideoPlayer, AudioPlayer, IframePlayer } from 'wini-web-components'
566
+
567
+ <VideoPlayer src="https://example.com/video.mp4" />
568
+ <AudioPlayer src="https://example.com/audio.mp3" />
569
+ <IframePlayer src="https://www.youtube.com/embed/dQw4w9WgXcQ" />
570
+ ```
571
+
572
+ ---
573
+
574
+ ### ImportFile / UploadFiles
575
+
576
+ File import input and multi-file uploader.
577
+
578
+ ```tsx
579
+ import { ImportFile, UploadFiles } from 'wini-web-components'
580
+
581
+ // Single file pick (no upload)
582
+ <ImportFile onChange={(file) => setFile(file)} accept=".pdf,.docx" />
583
+
584
+ // Upload to server
585
+ <UploadFiles
586
+ onComplete={(urls) => setAttachments(urls)}
587
+ maxFiles={5}
588
+ />
589
+ ```
590
+
591
+ ---
592
+
593
+ ### CustomCkEditor5
594
+
595
+ Rich text editor wrapper for CKEditor 5. Requires `ckeditor5` and `@ckeditor/ckeditor5-react` as peer dependencies.
596
+
597
+ ```tsx
598
+ import { CustomCkEditor5 } from 'wini-web-components'
599
+
600
+ <CustomCkEditor5 value={html} onChange={(html) => setHtml(html)} />
601
+ ```
602
+
603
+ ---
604
+
605
+ ### WiniEditor
606
+
607
+ Lightweight built-in rich text editor (no peer dependency required).
608
+
609
+ ```tsx
610
+ import { WiniEditor } from 'wini-web-components'
611
+
612
+ <WiniEditor value={content} onChange={(val) => setContent(val)} />
613
+ ```
614
+
615
+ ---
616
+
617
+ ### IconPicker
618
+
619
+ Searchable icon selector from the Wini icon library.
620
+
621
+ ```tsx
622
+ import { IconPicker } from 'wini-web-components'
623
+
624
+ <IconPicker value={icon} onChange={(iconName) => setIcon(iconName)} />
625
+ ```
626
+
627
+ ---
628
+
629
+ ---
630
+
631
+ ## Backend-Driven Modules
632
+
633
+ These components connect to the **Wini backend** and render entire UIs from server-side configuration (layouts, forms, cards, views). They require `WiniProvider` to be set up with a valid `pid` and `url`.
634
+
635
+ > All five components share a common customization API: `propsData`, `childrenData`, and `itemData` — which let you override specific elements by their **layer ID** (the `id` field set in the Wini editor for that element).
636
+
637
+ ---
638
+
639
+ ### PageById
640
+
641
+ Renders a full page (layout shell + body content) fetched from the backend by page ID. Typically used inside a `<Route>`.
642
+
643
+ ```tsx
644
+ import { PageById } from 'wini-web-components'
645
+
646
+ // Basic — renders the full page with its layout
647
+ <Route path="/dashboard" element={<PageById id="PAGE_ID" />} />
648
+
649
+ // Override props of a specific layer by its element ID
650
+ <PageById
651
+ id="PAGE_ID"
652
+ propsData={{
653
+ "element-gid": { style: { backgroundColor: 'red' }, className: 'my-class' }
654
+ }}
655
+ />
656
+
657
+ // Replace children of a layer entirely
658
+ <PageById
659
+ id="PAGE_ID"
660
+ childrenData={{
661
+ "element-gid": <MyCustomComponent />
662
+ }}
663
+ />
664
+
665
+ // Replace a layer entirely
666
+ <PageById
667
+ id="PAGE_ID"
668
+ itemData={{
669
+ "element-gid": <MyCustomComponent />
670
+ }}
671
+ />
672
+
673
+ // Render only the layout shell (without body content)
674
+ <PageById id="PAGE_ID" onlyLayout />
675
+
676
+ // Render only the body content (without layout shell)
677
+ <PageById id="PAGE_ID" onlyBody />
678
+ ```
679
+
680
+ ---
681
+
682
+ ### PageByUrl
683
+
684
+ Same as `PageById` but looks up the page by its **URL path** configured in the Wini backend. Useful for dynamic routing where page IDs are not known at build time.
685
+
686
+ ```tsx
687
+ import { PageByUrl } from 'wini-web-components'
688
+
689
+ // Renders the page registered under "/dashboard" in the Wini backend
690
+ <PageByUrl url="/dashboard" />
691
+
692
+ // Inject custom children into the layout body slot
693
+ <PageByUrl url="/dashboard" onlyLayout>
694
+ <MyBodyContent />
695
+ </PageByUrl>
696
+
697
+ // Same customization API as PageById
698
+ <PageByUrl
699
+ url="/dashboard"
700
+ propsData={{ "element-gid": { style: { color: 'blue' } } }}
701
+ childrenData={{ "element-gid": <CustomWidget /> }}
702
+ />
703
+ ```
704
+
705
+ ---
706
+
707
+ ### FormById
708
+
709
+ Renders a data-entry form from backend configuration by form ID. Manages its own `react-hook-form` state internally. Exposes an imperative ref for programmatic submit.
710
+
711
+ ```tsx
712
+ import { FormById } from 'wini-web-components'
713
+ import { useRef } from 'react'
714
+
715
+ const formRef = useRef(null)
716
+
717
+ // Basic — form submits and calls onSubmit with field values
718
+ <FormById
719
+ id="FORM_ID"
720
+ onSubmit={(data) => console.log('submitted:', data)}
721
+ onError={(errors) => console.error('validation failed:', errors)}
722
+ />
723
+
724
+ // Pre-populate with existing data (e.g. edit mode)
725
+ <FormById
726
+ id="FORM_ID"
727
+ data={{ Name: 'Alice', Age: 30 }}
728
+ onSubmit={(data) => updateRecord(data)}
729
+ />
730
+
731
+ // Load data from backend by query
732
+ <FormById
733
+ id="FORM_ID"
734
+ controller={{ searchRaw: '@Id:{some-id}' }}
735
+ onSubmit={(data) => updateRecord(data)}
736
+ />
737
+
738
+ // Load data from backend by IDs
739
+ <FormById
740
+ id="FORM_ID"
741
+ controller={{ ids: 'id1,id2', maxLength: 1 }}
742
+ onSubmit={(data) => updateRecord(data)}
743
+ />
744
+
745
+ // Trigger submit programmatically via ref
746
+ <FormById ref={formRef} id="FORM_ID" onSubmit={handleSubmit} />
747
+ <Button label="Save" onClick={() => formRef.current?.onSubmit()} />
748
+
749
+ // Supply custom dropdown options for a relation field
750
+ <FormById
751
+ id="FORM_ID"
752
+ customOptions={{ categoryId: [{ id: '1', name: 'Tech' }, { id: '2', name: 'Art' }] }}
753
+ onSubmit={handleSubmit}
754
+ />
755
+
756
+ // Customize a specific field's wrapper props or replace it entirely
757
+ <FormById
758
+ id="FORM_ID"
759
+ propsData={{ "field-element-gid": { style: { display: 'none' } } }}
760
+ itemData={{ "field-element-gid": <MyCustomField /> }}
761
+ onSubmit={handleSubmit}
762
+ />
763
+ ```
764
+
765
+ **Ref handle:**
766
+ ```ts
767
+ formRef.current.onSubmit() // trigger submit programmatically
768
+ formRef.current.methods // UseFormReturn — full react-hook-form instance
769
+ formRef.current.cols // resolved column definitions from backend
770
+ formRef.current.rels // resolved relation definitions from backend
771
+ ```
772
+
773
+ ---
774
+
775
+ ### CardById
776
+
777
+ Renders a **repeating list** of items using a card template configured in the backend. Fetches its own data, supports pagination, filtering, sorting, and exposes a ref for imperative data refresh.
778
+
779
+ ```tsx
780
+ import { CardById } from 'wini-web-components'
781
+ import { useRef } from 'react'
782
+
783
+ const cardRef = useRef(null)
784
+
785
+ // Basic — fetches and renders all items
786
+ <CardById id="CARD_ID" />
787
+
788
+ // With query controller (search + pagination)
789
+ <CardById
790
+ id="CARD_ID"
791
+ controller={{ page: 1, size: 10, searchRaw: '@Status:{active}', sortby: [{ prop: 'Name', direction: 'ASC' }] }}
792
+ onLoaded={({ data, totalCount }) => setTotal(totalCount)}
793
+ />
794
+
795
+ // Provide data directly (skip backend fetch)
796
+ <CardById
797
+ id="CARD_ID"
798
+ cardData={[{ Id: '1', Name: 'Item A' }, { Id: '2', Name: 'Item B' }]}
799
+ />
800
+
801
+ // Fetch all records
802
+ <CardById id="CARD_ID" controller="all" />
803
+
804
+ // Custom render per item — functions receive (itemData, index, methods)
805
+ <CardById
806
+ id="CARD_ID"
807
+ propsData={{
808
+ "element-gid": (item, index) => ({ style: { color: item.IsActive ? 'green' : 'red' } })
809
+ }}
810
+ childrenData={{
811
+ "element-gid": (item, index) => <span>{item.Name}</span>
812
+ }}
813
+ itemData={{
814
+ "element-gid": (item, index) => <MyCustomRow data={item} />
815
+ }}
816
+ />
817
+
818
+ // Empty state
819
+ <CardById id="CARD_ID" emptyMessage="No items found" emptyLink="/create" />
820
+
821
+ // Imperative refresh
822
+ <CardById ref={cardRef} id="CARD_ID" controller={{ page: 1, size: 10, searchRaw: '*' }} />
823
+ <Button label="Refresh" onClick={() => cardRef.current?.getData(1)} />
824
+ ```
825
+
826
+ **Ref handle:**
827
+ ```ts
828
+ cardRef.current.getData(page?) // re-fetch data (optionally set page)
829
+ cardRef.current.data // { data: Array<{...}>, totalCount?: number }
830
+ cardRef.current.setData(newData) // manually update rendered data
831
+ cardRef.current.controller // current active query controller
832
+ ```
833
+
834
+ ---
835
+
836
+ ### ViewById
837
+
838
+ Renders a **single item detail view** from backend configuration. Similar to `CardById` but for one record instead of a list.
839
+
840
+ ```tsx
841
+ import { ViewById } from 'wini-web-components'
842
+
843
+ // Pass data directly (e.g. from a parent list)
844
+ <ViewById
845
+ id="VIEW_ID"
846
+ data={{ Id: 'abc', Name: 'Alice', Email: 'alice@example.com' }}
847
+ />
848
+
849
+ // Or let it fetch by query
850
+ <ViewById
851
+ id="VIEW_ID"
852
+ controller={{ searchRaw: `@Id:{${recordId}}` }}
853
+ onLoaded={({ data }) => setRecord(data)}
854
+ />
855
+
856
+ // Override specific elements — same API as PageById/CardById
857
+ <ViewById
858
+ id="VIEW_ID"
859
+ data={record}
860
+ propsData={{ "label-gid": { style: { fontWeight: 'bold' } } }}
861
+ childrenData={{ "value-gid": <strong>{record.Name}</strong> }}
862
+ />
863
+ ```
864
+
865
+ ---
866
+
867
+ ## Responsive Grid Classes
868
+
869
+ The layout system uses a **24-column grid**. Add these classes to children inside a `row`.
870
+
871
+ | Class | Columns | Notes |
872
+ |---|---|---|
873
+ | `col1` – `col24` | 1/24 – 24/24 | Always applied |
874
+ | `remain` | fills rest | `flex: 1` |
875
+ | `col1-min` – `col24-min` | at **< 576px** | phones |
876
+ | `col1-sm` – `col24-sm` | at **≥ 576px** | small devices |
877
+ | `col1-md` – `col24-md` | at **≥ 768px** | tablets |
878
+ | `col1-lg` – `col24-lg` | at **≥ 992px** | laptops |
879
+ | `col1-xl` – `col24-xl` | at **≥ 1200px** | desktops |
880
+ | `col1-xxl` – `col24-xxl` | at **> 1200px** | wide screens |
881
+
882
+ ```tsx
883
+ // 2-column on desktop, stacks on mobile
884
+ <div className="row" style={{ gap: 16 }}>
885
+ <div className="col24 col12-lg">Left panel</div>
886
+ <div className="col24 col12-lg">Right panel</div>
887
+ </div>
888
+ ```
889
+
890
+ ---
891
+
892
+ ## Design Tokens & Theming
893
+
894
+ Colors are defined as CSS variables in `root.css` and can be overridden by WiniProvider at runtime.
895
+
896
+ ```css
897
+ /* Default token examples */
898
+ --primary-main-color: #287CF0;
899
+ --primary-bolder-color: #0F62D7;
900
+ --neutral-bolder-border: 1px solid #D7D7DB;
901
+ /* semantic */
902
+ --success-main-color: ...;
903
+ --error-main-color: ...;
904
+ --warning-main-color: ...;
905
+ ```
906
+
907
+ Dark mode is toggled by adding the `.dark` class to `<html>`. Use `setTheme` from `useWiniContext`:
19
908
 
20
- ## Using Skin:
21
- add this cdn link into your App.css file. \
22
- @import url(https://cdn.jsdelivr.net/gh/WiniGit/web-component@latest/src/skin/root.css); \
23
- @import url(https://cdn.jsdelivr.net/gh/WiniGit/web-component@latest/src/skin/typography.css); \
24
- @import url(https://cdn.jsdelivr.net/gh/WiniGit/web-component@latest/src/skin/layout.css); \
25
- \
26
- row: for horizontal layout. \
27
- col: for vertical layout.
28
-
29
- ## Responsive Design:
30
- wini-web-components comes with built-in CSS classes to ensure your UI looks great on all devices. The library supports responsive layouts for:\
31
- Min Devices (Small phones): < 576px. \
32
- Small Devices (Phones): Up to 576px. \
33
- Medium Devices (Tablets): 576px to 768px. \
34
- Large Devices (Laptops): 768px to 992px. \
35
- Extra Large Devices (Desktops): 992px to 1200px. \
36
- Extra Extra Large Devices: > 1200px. \
37
- Each component is designed to adapt seamlessly to different screen sizes, with CSS classes: \
38
- Ex: remain, col0, col1, col2, col3, col4, col6, col8, col10, col12, col16, col18, col20, col24, col1-min, col2-min, col3-sm, col6-sm, col8-md, col10-lg, col12-lg, col16-xl, col18-xl, col20-xxl, col24-xxl
39
-
40
- ## Using code features:
41
- Components
42
- wini-web-components includes the following UI components, ready to drop into your React project:
43
- ### Button: A versatile button component with multiple styles.
44
- support className: \
45
- Ex: size64, size56, size48, size40, size24, default is size32. button-grey, button-primary, button-neutral, button-black, button-white, button-infor, button-warning, button-error, button-success, button-infor-main, button-warning-main, button-error-main, button-success-main
46
- ### WiniIcon: A custom icon component for your app.
47
- support className: \
48
- Ex: icon-button, light, size64, size56, size48, size40, size32, size24.
49
-
50
- ### Calendar: A date selection component for scheduling and events.
51
- ### Carousel: A slideshow component for displaying images or content.
52
- ### Checkbox: A customizable checkbox for forms.
53
- ### CK-Editor: A rich text editor integration for content creation.
54
- ### Date-Time-Picker: A component for selecting dates and times.
55
- ### Dialog: A modal dialog for alerts, forms, or custom content.
56
- ### Input-File: A file upload input with a clean UI.
57
- ### Input-Multi-Select: A multi-select dropdown for forms.
58
- ### Input-Text: A styled text input field.
59
- ### Input-Textarea: A textarea for longer text input.
60
- ### Number-Picker: A component for selecting numerical values.
61
- ### Pagination: A pagination component for navigating large datasets.
62
- ### Popup: A popup component for notifications or overlays.
63
- ### Progress-Bar: A progress bar to show task completion.
64
- ### Progress-Circle: A circular progress indicator.
65
- ### Radio-Button: A radio button for single-choice selections.
66
- ### Rating: A star rating component for reviews or feedback.
67
- ### Select: A dropdown select component for forms.
68
- ### Slider: A slider for selecting a range of values.
69
- ### Switch: A toggle switch for on/off states.
70
- ### Table: A responsive table for displaying tabular data.
71
- ### Tag: A tag component for categorization or labeling.
72
- ### Text-Area: A textarea with additional styling options.
73
- ### Text-Field: A general-purpose text input field.
909
+ ```tsx
910
+ const { setTheme } = useWiniContext()
911
+ setTheme('dark') // adds .dark to <html>
912
+ setTheme('light') // removes .dark from <html>
913
+ ```
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "wini-web-components",
3
3
  "private": false,
4
4
  "description": "A simple ui library for React",
5
- "version": "8.4.97",
5
+ "version": "8.4.98",
6
6
  "main": "dist/index.umd.js",
7
7
  "module": "dist/index.es.js",
8
8
  "types": "dist/index.d.ts",