wini-web-components 8.4.97 → 8.4.99

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