UNPKG

18 kBMarkdownView Raw
1# ![logo](/demo/src/assets/logo-small.png) web-ui-pack
2
3Web package with high scalable [WebComponents](#components) and [helpers](#helpers)
4
5[![npm version](https://img.shields.io/npm/v/web-ui-pack.svg?style=flat-square)](https://www.npmjs.com/package/web-ui-pack)
6[![code coverage](https://coveralls.io/repos/github/Yegorich555/web-ui-pack/badge.svg?style=flat-square)](https://coveralls.io/github/Yegorich555/web-ui-pack)
7[![install size](https://packagephobia.now.sh/badge?p=web-ui-pack)](https://packagephobia.now.sh/result?p=web-ui-pack)
8[![npm downloads](https://img.shields.io/npm/dm/web-ui-pack.svg?style=flat-square)](http://npm-stat.com/charts.html?package=web-ui-pack)
9[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
11## Demo
12
13You can see demo [here](https://yegorich555.github.io/web-ui-pack) or just clone repo and run `npm i & npm start`
14
15## Features
16
17- Possible to use **with/without** any frameworks like Angular, React, Vue etc. (because it's js-native logic)
18- Form/controls are ready to use and has built-in completed validation logic for any case that you can imagine (see [demo/controls](https://yegorich555.github.io/web-ui-pack/controls))
19- Focus on accessibility (best practices), other packages has low-accessibility support
20- High scalable and easy customizable (every component is developed to easy inherit and redefine/extend default logic)
21- Built-in css-variables to use custom color-themes with native ordinary styling (css, scss etc.)
22- Built-in Typescript (coverage types 100%)
23- Built-in `.jsx/.tsx` support (for React/Vue)
24- Supports different locales (based on [localeInfo](src/objects/localeInfo.ts) helper)
25- Well documented via JSDoc (use intellisense power of your editor to get details about each property/option/usage)
26- Optimized for webpack (build includes only used components and helpers via **side-effects** option)
27- Zero dependancy (don't need to wait for bug-fixing of other packages)
28- Always 100% test coverage via e2e and unit tests (it's must-have and always will be so)
29- Focus on performance (it's important to have low-memory consumption and fastest initialization)
30
31## Why the package is so big
32
33It's developed with [Typescript](https://www.typescriptlang.org/) and has huge built-in documentation (JSDoc). Every method,property,event is documented well so you don't need extra resource to take an example to implement or configure elements. In build-result without comments you will see that it's small-enough
34
35## Installing
36
37Using npm:
38
39```npm
40npm install web-ui-pack
41```
42
43## TODO
44
45- [x] [Helpers](#helpers)
46- [x] [PopupElement](#example) [**demo**](https://yegorich555.github.io/web-ui-pack/popup)
47 - [ ] Tooltip
48- [x] [SpinElement](src/spinElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/spin)
49- [x] [CircleElement](src/circleElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/circle)
50- [x] [FormElement](src/formElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/controls)
51 - [x] [TextControl](src/controls/text.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/text)
52 - [x] [Mask/pattern for controls](src/controls//text.mask.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/text)
53 - [x] [PasswordControl](src/controls/password.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/password)
54 - [x] [SwitchControl (Toggler)](src/controls/switch.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/switch)
55 - [x] [CheckControl (Checkbox)](src/controls/check.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/check)
56 - [ ] CheckTreeControl
57 - [x] [RadioControl (RadioGroup)](src/controls/radio.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/radio)
58 - [x] [SelectControl (ComboBox)](src/controls/select.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/select)
59 - [x] [SelectManyControl (MultiSelect)](src/controls/selectMany.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/selectMany)
60 - [x] [CalendarControl](src/controls/calendar.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/calendar)
61 - [x] [DateControl](src/controls/date.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/date)
62 - [x] [TimeControl](src/controls/time.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/time)
63 - [ ] DateTimeControl ?
64 - [x] [TextareaControl](src/controls/textarea.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/textarea)
65 - [x] [NumberControl](src/controls/number.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/number)
66 - [ ] SliderControl (progress bar)
67 - [ ] FileControl
68 - [ ] SearchControl ?
69 - [ ] ImageControl (AvatarEditor)
70- [x] [DropdownElement](src/dropdownElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/dropdown)
71- [ ] MediaPlayer
72- [ ] ModalElement
73- [ ] ConfirmModalElement
74- [ ] FormModalElement
75- [ ] InfiniteScroll
76- [ ] VirtualScroll
77- [ ] CarouselElement (Slide show)
78- [ ] TableElement ?
79
80## Components
81
82**Common rules**:
83
841. **Naming**
85 - All components named as `WUP..Element`, `WUP..Control` and has `<wup-...>` html-tags
86 - Public properties/options/events/methods startsWith `$...` (events `$onShow`, `$onHide`, methods `$show`, `$hide`, props like `$isShown` etc.)
87 - Every component/class has static `$defaults` (common options for current class) and personal `$options` (per each component). See details in [example](#example)
88 - `$options` are observed. So changing options affects on component immediately after empty timeout (every component has static `observedOptions` as set of watched options)
89 - all custom `attributes` updates `$options` automatically. So `document.querySelector('wup-spin').$options.inline` equal to `<wup-spin inline />`
902. **Usage**
91 - For webpack [sideEffects](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) switched on (for optimization). But **if you don't use webpack** don't import from `web-ui-pack` directly (due to tree-shaking can be not smart enough). Instead use `web-ui-pack/path-to-element`
92 - Every component has a good JSDoc so go ahead and read details directly during the coding
93 - Library compiled into ESNext. To avoid unexpected issues include this package into babel (use `exclude: /node_modules\/(?!(web-ui-pack)\/).*/` for babel-loader)
943. **Limitations**
95 - In `jsx/tsx` instead of `className` use `class` attribute (React issue)
96 - If you change custom html-attributes it will update `$options`, but if you change some option it removes related attribute (for performance reasons). Better to avoid usage attributes at all
974. **Inheritance**
98 - Components are developed to be easy customized and inherited. Use ...$defaults of every class to configure behavior You can rewrite everything that you can imagine without digging a lot in a code. To be sure don't hesitate to take a look on \*.d.ts or source code (there are enough comments to clarify even weird/difficult cases)
99 - All Components inherited from [WUPBaseElement](src/baseElement.ts) that extends default HTMLElement
100 - All internal event-callbacks startsWith `got...` (gotReady, gotRemoved)
101 - To redefine component just extend it and register with new html tag OR redefine default behavior via prototype functions (if $defaults are not included something). See details in [example](#example)
102 - **Inheritance Tree**
103 - [_HTMLElement_](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement)
104 - [_BaseElement_](src/baseElement.ts)
105 - [PopupElement](src/popupElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/popup)
106 - [DropdownElement](src/dropdownElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/dropdown)
107 - [SpinElement](src/spinElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/spin)
108 - [CircleElement](src/circleElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/circle)
109 - [FormElement](src/formElement.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/controls)
110 - [_BaseControl_](src/controls/baseControl.ts)
111 - [SwitchControl](src/controls/switch.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/switch)
112 - [CheckControl](src/controls/check.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/check)
113 - [RadioControl](src/controls/radio.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/radio)
114 - [TextControl](src/controls/text.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/text)
115 - [TextareaControl](src/controls/textarea.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/textarea)
116 - [PasswordControl](src/controls/password.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/password)
117 - [NumberControl](src/controls/number.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/number)
118 - [_BaseComboControl_](src/controls/baseCombo.ts)
119 - [SelectControl](src/controls/select.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/select)
120 - [SelectManyControl](src/controls/selectMany.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/selectMany)
121 - [DateControl](src/controls/date.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/date)
122 - [TimeControl](src/controls/time.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/time)
123 - [CalendarControl](src/controls/calendar.ts) [**demo**](https://yegorich555.github.io/web-ui-pack/control/calendar)
124
125---
126
127### Example
128
129Check how you can use every element/control (popupElement for example)
130Also check [code style example](/CODESTYLE.md)
131
132Typescript
133
134```typescript
135import WUPPopupElement, { ShowCases } from "web-ui-pack/popup/popupElement";
136
137// redefine some defaults; WARN: you can change placement rules here without changing $options per each element!!!
138WUPPopupElement.$defaults.offset = [2, 2];
139WUPPopupElement.$defaults.minWidthByTarget = true;
140WUPPopupElement.$defaults.arrowEnable = true;
141
142// create element
143const el = document.createElement("wup-popup");
144// WARN el.$options is a observable-clone of WUPPopupElement.$defaults
145// WARN: ShowCases is const enum and import ShowCases available only in Typescript
146el.$options.showCase = ShowCases.onClick | ShowCases.onFocus; // show popup by target.click and/or target.focus events
147el.$options.target = document.querySelector("button");
148/*
149 Placement can be $top, $right, $bottom, $left (top - above at the target etc.)
150 every placement has align options: $start, $middle, $end (left - to align at start of target)
151 also you can set $adjust to allow Reduce popup to fit layout
152*/
153el.$options.placement = [
154 WUPPopupElement.$placements.$top.$middle; // place at the top of target and align by vertical line
155 WUPPopupElement.$placements.$bottom.$middle.$adjust, // adjust means 'ignore align to fit layout`
156 WUPPopupElement.$placements.$bottom.$middle.$adjust.$resizeHeight, // resize means 'allow to resize to fit layout'
157]
158document.body.append(el);
159```
160
161HTML, JSX, TSX
162
163```html
164<button id="btn1">Target</button>
165<!-- You can skip pointing attribute 'target' if popup appended after target -->
166<wup-popup target="#btn1" placement="top-start">Some content here</wup-popup>
167```
168
169How to extend/override
170
171```typescript
172/// popup.ts
173
174// you can override via prototypes
175const original = WUPPopupElement.prototype.goShow;
176WUPPopupElement.prototype.goShow = function customGoShow() {
177 if (window.isBusy) {
178 return null;
179 }
180 return original(...arguments);
181};
182
183/*** OR create extended class ***/
184
185class Popup extends WUPPopupElement {
186 // take a look on definition of WUPPopupElement and you will find internals
187 protected override goShow(showCase: WUPPopup.ShowCases): boolean {
188 if (showCase === WUPPopup.ShowCases.onHover) {
189 return false;
190 }
191 return super.goShow(showCase);
192 }
193}
194
195const tagName = "ext-popup";
196customElements.define(tagName, Popup);
197// That's it. New Popup with custom tag 'ext-popup' is ready
198
199// add for intellisense (for *.ts only)
200declare global {
201 // add element to document.createElement
202 interface HTMLElementTagNameMap {
203 [tagName]: Popup;
204 }
205
206 // add element for tsx/jsx intellisense
207 namespace JSX {
208 interface IntrinsicElements {
209 [tagName]: IntrinsicElements["wup-popup"];
210 }
211 }
212}
213```
214
215---
216
217### Helpers
218
219use `import focusFirst from "web-ui-pack/helpers/focusFirst"` etc.
220**WARN**: don't use `import {focusFirst} from "web-ui-pack;` because in this case the whole web-ui-pack module traps in compilation of dev-bundle and increases time of compilation
221
222- [**animateDropdown**](src/helpers/animateDropdown.ts) ⇒ `Animate (show/hide) element as dropdown via scale and counter-scale for children`
223- [**animateStack**](src/helpers/animateDropdown.ts) ⇒ `Animate (show/hide) every element via moving from target to own position`
224- [**dateCopyTime**](src/helpers/dateCopyTime.ts) ⇒ `Copy hh:mm:ss.fff part from B to A`
225- [**dateFromString**](src/helpers/dateFromString.ts) ⇒ `Returns parsed date from string based on pointed format`
226- [**dateToString**](src/helpers/dateToString.ts) ⇒ `Returns a string representation of a date-time according to pointed format`
227- [**findScrollParent**](src/helpers/findScrollParent.ts) ⇒ `Find first parent with active scroll X/Y`
228- [**findScrollParentAll**](src/helpers/findScrollParent.ts) ⇒ `Find all parents with active scroll X/Y`
229- [**focusFirst**](src/helpers/focusFirst.ts) ⇒ `Set focus on element or first possible nested element`
230- [**isIntoView**](src/helpers/isIntoView.ts) ⇒ `Check if element is visible in scrollable parents`
231- [**mathSumFloat**](src/helpers/math.ts) ⇒ `Sum without float-precision-issue`
232- [**mathScaleValue**](src/helpers/math.ts) ⇒ `Scale value from one range to another`
233- [**nestedProperty.set**](src/helpers/nestedProperty.ts) ⇒ `nestedProperty.set(obj, "value.nestedValue", 1) sets obj.value.nestedValue = 1`
234- [**nestedProperty.get**](src/helpers/nestedProperty.ts) ⇒ `nestedProperty.get(obj, "nested.val2", out?: {hasProp?: boolean} ) returns value from obj.nested.val2`
235- [**objectClone**](src/helpers/objectClone.ts) ⇒ `deep cloning object`
236- [**observer**](src/helpers/observer.md) ⇒ `converts object to observable (via Proxy) to allow listen for changes`
237- [**onEvent**](src/helpers/onEvent.ts) ⇒ `More strict (for Typescript) wrapper of addEventListener() that returns callback with removeListener()`
238- [**onFocusGot**](src/helpers/onFocusGot.ts) ⇒ `Fires when element/children takes focus once (fires again after onFocusLost on element)`
239- [**onScroll**](src/helpers/onScrollStop.ts) ⇒ `Handles wheel & touch events for custom scrolling`
240- [**onScrollStop**](src/helpers/onScrollStop.ts) ⇒ `Returns callback when scrolling is stopped (via checking scroll position every frame-render)`
241- [**onFocusLost**](src/helpers/onFocusLost.ts) ⇒ `Fires when element/children completely lost focus`
242- [**onSpy**](src/helpers/onSpy.ts) ⇒ `Spy on method-call of object`
243- [**promiseWait**](src/helpers/promiseWait.ts) ⇒ `Produce Promise during for "no less than pointed time"; it helps for avoding spinner blinking during the very fast api-request in case: pending > waitResponse > resetPending`
244- [**scrollIntoView**](src/helpers/scrollIntoView.ts) ⇒ `Scroll the HTMLElement's parent container such that the element is visible to the user and return promise by animation end`
245- [class **WUPScrolled**](src/helpers/scrolled.ts) ⇒ `Class makes pointed element scrollable and implements carousel-scroll behavior (appends new items during the scrolling). Supports swipe/pageUp/pageDown/mouseWheel events.`
246- [**stringLowerCount**](src/helpers/string.ts) ⇒ `Returns count of chars in lower case (for any language with ignoring numbers, symbols)`
247- [**stringUpperCount**](src/helpers/string.ts) ⇒ `Returns count of chars in upper case (for any language with ignoring numbers, symbols)`
248- [**stringPrettify**](src/helpers/string.ts) ⇒ `Changes camelCase, snakeCase, kebaCase text to user-friendly`
249
250### Objects
251
252- [**localeInfo**](src/objects/localeInfo.ts) ⇒ `Locale-object with definitions related to user-locale`
253- [**TimeObject**](src/objects/timeObject.ts) ⇒ `Plane time object without date`
254
255---
256
257### Troubleshooting
258
259Be sure that you familiar with [common rules](#components)
260
261#### Library doesn't work in some browsers
262
263> web-ui-pack is compiled to ESNext. So some features maybe don't exist in browsers. To resolve it include the lib into babel-loader (for webpack check module.rules...exclude sections
264>
265> ```js
266> // webpack.config.js
267> {
268> test: /\.(js|jsx)$/,
269> exclude: (() => {
270> // these packages must be included to change according to browserslist
271> const include = ["web-ui-pack"];
272> return (v) => v.includes("node_modules") && !include.some((lib) => v.includes(lib));
273> })(),
274> use: [ "babel-loader", ],
275> },
276> ```
277
278#### UI doesn't recognize html tags like `<wup-popup />` etc
279
280> It's possible if you missed import or it was removed by optimizer of wepback etc. To fix this you need to force import at least once
281>
282> ```js
283> import { WUPSelectControl, WUPTextControl } from "web-ui-pack";
284>
285> // this force webpack not ignore imports (if imported used only as html-tags without direct access)
286> const sideEffect = WUPTextControl && WUPSelectControl;
287> !sideEffect && console.error("Missed"); // It's required otherwise import is ignored by webpack
288> // or
289> WUPTextControl.$defaults.validateDebounceMs = 500;
290> WUPSelectControl.$defaults.validateDebounceMs = 500;
291> // etc.
292> ```
293
294### FAQ
295
296see [demo/faq](https://yegorich555.github.io/web-ui-pack/faq)