kitzo 1.0.4 → 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 CHANGED
@@ -10,6 +10,7 @@ Current features
10
10
  - Tooltip on mouseover
11
11
  - Ripple effect on mousedown
12
12
  - Debounce function
13
+ - Hover clip-path effect
13
14
 
14
15
  #### Install
15
16
 
@@ -17,10 +18,10 @@ Current features
17
18
  npm i kitzo
18
19
  ```
19
20
 
20
- > or
21
+ or
21
22
 
22
23
  ```javascript
23
- <script src="https://cdn.jsdelivr.net/npm/kitzo@1.0.3/dist/kitzo.umd.min.js"></script>
24
+ <script src="https://cdn.jsdelivr.net/npm/kitzo@1.1.0/dist/kitzo.umd.min.js"></script>
24
25
  ```
25
26
 
26
27
  > Attach this script tag in the html head tag and you are good to go.
@@ -29,24 +30,27 @@ npm i kitzo
29
30
 
30
31
  #### Quick usage overview
31
32
 
32
- | [NPM](#npm-usage) | [CDN](#cdn-usage) |
33
- | -------------------------------- | ------------------------------------- |
34
- | [`kitzoCopy()`](#copy-api) | [`kitzo.copy()`](#copy-api-1) |
35
- | [`kitzoTooltip()`](#tooltip-api) | [`kitzo.tooltip()`](#tooltip-api-1) |
36
- | [`kitzoRipple()`](#ripple-api) | [`kitzo.ripple()`](#ripple-api-1) |
37
- | [`kitzoDebounce()`](#debounce) | [`kitzo.debounce()`](#debounce-api-1) |
38
-
39
- #### NPM usage
40
-
41
33
  ```javascript
42
- import { kitzoCopy, kitzoTooltip, kitzoRipple, kitzoDebounce } from 'kitzo';
34
+ // NPM usage
35
+ import kitzo from 'kitzo';
43
36
  ```
44
37
 
38
+ | [API](#apis) |
39
+ | ----------------------------------- |
40
+ | [`kitzo.copy()`](#copy-api) |
41
+ | [`kitzo.tooltip()`](#tooltip-api) |
42
+ | [`kitzo.ripple()`](#ripple-api) |
43
+ | [`kitzo.debounce()`](#debounce-api) |
44
+ | [`kitzo.clippath()`](#clippath-api) |
45
+
46
+ #### APIs
47
+
45
48
  ```javascript
46
- kitzoCopy();
47
- kitzoTooltip();
48
- kitzoRipple();
49
- kitzoDebounce();
49
+ kitzo.copy();
50
+ kitzo.tooltip();
51
+ kitzo.ripple();
52
+ kitzo.debounce();
53
+ kitzo.clippath();
50
54
  ```
51
55
 
52
56
  > Use a modern build tool. **vite** - recommended
@@ -71,7 +75,7 @@ kitzoTooltip(selectors | element | NodeList, {
71
75
  arrow: 'on' | 'off',
72
76
  offset: number,
73
77
  customClass: string,
74
- style: {},
78
+ style: object,
75
79
  });
76
80
  ```
77
81
 
@@ -84,7 +88,7 @@ kitzoRipple(selectors | element | NodeList, {
84
88
  opacity: number,
85
89
  duration: number,
86
90
  color: string,
87
- size: number | null,
91
+ size: number,
88
92
  });
89
93
  ```
90
94
 
@@ -110,68 +114,13 @@ document.querySelector('#search').addEventListener('input', (e) => {
110
114
 
111
115
  > Debounce on every call of function.
112
116
 
113
- ---
114
-
115
- #### CDN usage
116
-
117
- ```html
118
- <script src="https://cdn.jsdelivr.net/npm/kitzo@1.0.0/dist/kitzo.umd.min.js"></script>
119
- ```
120
-
121
- ```javascript
122
- kitzo.copy();
123
- kitzo.tooltip();
124
- kitzo.ripple();
125
- kitzo.debounce();
126
- ```
127
-
128
- ##### Copy API:
117
+ ##### Clippath API:
129
118
 
130
119
  ```javascript
131
- kitzo.copy(selectors | element, {
132
- doc: string,
133
- event: 'click' | 'dblclick' | 'contextmenu' | 'mouseup' | 'touchend',
134
- });
135
- ```
136
-
137
- ##### Tooltip API:
138
-
139
- ```javascript
140
- kitzo.tooltip(selectors | element | NodeList, {
141
- tooltip: string,
142
- direction: 'top' | 'right' | 'bottom' | 'left',
143
- arrow: 'on' | 'off',
144
- offset: number,
145
- customClass: string,
146
- style: {},
147
- });
148
- ```
149
-
150
- ##### Ripple API:
151
-
152
- ```javascript
153
- kitzo.ripple(selectors | element | NodeList, {
154
- opacity: number,
155
- duration: number,
156
- color: string,
157
- size: number | null,
158
- });
159
- ```
160
-
161
- ##### Debounce API:
162
-
163
- ```javascript
164
- kitzo.debounce(callback, delayInMilliseconds);
165
- ```
166
-
167
- ```javascript
168
- // Log only after typing stops for 500ms
169
- const logSearch = kitzo.debounce((text) => {
170
- console.log('Searching for:', text);
171
- }, 500);
172
-
173
- // Attach to input
174
- document.querySelector('#search').addEventListener('input', (e) => {
175
- logSearch(e.target.value);
120
+ kitzo.clippath(selectors | element | NodeList, {
121
+ text: string,
122
+ clippathSize: string | number,
123
+ smooth: boolean,
124
+ style: object,
176
125
  });
177
126
  ```
package/dist/kitzo.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export function kitzoTooltip(
2
- element: string | Element | NodeListOf<Element> | HTMLCollection,
1
+ export function tooltip(
2
+ element: string | Element | NodeListOf<Element>,
3
3
  config?: {
4
4
  /**
5
5
  * The tooltip text to display (default: "Tool tip")
@@ -33,8 +33,8 @@ export function kitzoTooltip(
33
33
  }
34
34
  ): void;
35
35
 
36
- export function kitzoRipple(
37
- element: string | Element | NodeListOf<Element> | HTMLCollection,
36
+ export function ripple(
37
+ element: string | Element | NodeListOf<Element>,
38
38
  config?: {
39
39
  /**
40
40
  * Ripple opacity (0 to 1). Default: 0.5
@@ -55,7 +55,7 @@ export function kitzoRipple(
55
55
  }
56
56
  ): void;
57
57
 
58
- export function kitzoCopy(
58
+ export function copy(
59
59
  element: string | Element | NodeListOf<Element>,
60
60
  config: {
61
61
  /**
@@ -77,4 +77,14 @@ export function kitzoCopy(
77
77
  }
78
78
  ): void;
79
79
 
80
- export function kitzoDebounce<Args extends any[]>(fn: (...args: Args) => any, delay?: number): (...args: Args) => void;
80
+ export function debounce<Args extends any[]>(fn: (...args: Args) => any, delay?: number): (...args: Args) => void;
81
+
82
+ export function clippath(
83
+ element: string | Element | NodeListOf<Element>,
84
+ config?: {
85
+ text?: String;
86
+ clippathSize?: String | Number;
87
+ smooth?: Boolean;
88
+ style?: Partial<CSSStyleDeclaration>;
89
+ }
90
+ ): void;
package/dist/kitzo.esm.js CHANGED
@@ -1,4 +1,5 @@
1
1
  //! Helper functions
2
+ // Get elements from dom
2
3
  function getButtons(element) {
3
4
  if (typeof element === 'string') {
4
5
  return document.querySelectorAll(element);
@@ -14,6 +15,7 @@ function getButtons(element) {
14
15
  // Add style tags
15
16
  let tooltipStyleAdded = false;
16
17
  let rippleStyleAdded = false;
18
+ let clippathStyleAdded = false;
17
19
 
18
20
  function addStyleTag(styles) {
19
21
  const style = document.createElement('style');
@@ -30,6 +32,10 @@ function addStyleTagToHtmlHead(type, styles) {
30
32
  addStyleTag(styles);
31
33
  rippleStyleAdded = true;
32
34
  }
35
+ if (type === 'clippath' && !clippathStyleAdded) {
36
+ addStyleTag(styles);
37
+ clippathStyleAdded = true;
38
+ }
33
39
  }
34
40
 
35
41
  //! Copy function
@@ -64,7 +70,7 @@ const copyConfigMap = new WeakMap();
64
70
  const allowedEvents = ['click', 'dblclick', 'contextmenu', 'mouseup', 'touchend'];
65
71
  const attachedEvents = new Set();
66
72
 
67
- function kitzoCopy(element, config = {}) {
73
+ function copy(element, config = {}) {
68
74
  config = Object.assign(
69
75
  {
70
76
  doc: '',
@@ -102,18 +108,18 @@ function kitzoCopy(element, config = {}) {
102
108
 
103
109
  const allButtons = getButtons(element);
104
110
  if (!allButtons) {
105
- console.error('No elements found for zeroCopy');
111
+ console.error('No elements found for kitzoCopy');
106
112
  return;
107
113
  }
108
114
 
109
115
  if (!allowedEvents.includes(event)) {
110
- console.warn(`[zeroCopy] "${event}" is not allowed. Defaulting to "click".`);
116
+ console.warn(`[kitzo.copy] "${event}" is not allowed. Defaulting to "click".`);
111
117
  }
112
118
 
113
119
  const safeEvent = allowedEvents.includes(event) ? event : 'click';
114
120
 
115
121
  allButtons.forEach((btn) => {
116
- btn.setAttribute('data-zero-copy', 'true');
122
+ btn.setAttribute('data-kitzo-copy', 'true');
117
123
 
118
124
  copyConfigMap.set(btn, {
119
125
  doc,
@@ -123,7 +129,7 @@ function kitzoCopy(element, config = {}) {
123
129
 
124
130
  if (!attachedEvents.has(safeEvent)) {
125
131
  document.addEventListener(safeEvent, (e) => {
126
- const btn = e.target.closest('[data-zero-copy]');
132
+ const btn = e.target.closest('[data-kitzo-copy]');
127
133
  if (!btn) return;
128
134
 
129
135
  const { doc, event } = copyConfigMap.get(btn);
@@ -135,7 +141,7 @@ function kitzoCopy(element, config = {}) {
135
141
  }
136
142
  }
137
143
 
138
- function kitzoDebounce(fn, delay = 300) {
144
+ function debounce(fn, delay = 300) {
139
145
  let timer;
140
146
 
141
147
  return (...args) => {
@@ -145,12 +151,12 @@ function kitzoDebounce(fn, delay = 300) {
145
151
  }
146
152
 
147
153
  function rippleStyles() {
148
- return `.zero-ripple {
154
+ return `.kitzo-ripple {
149
155
  position: relative;
150
156
  overflow: hidden;
151
157
  }
152
158
 
153
- .zero-ripples {
159
+ .kitzo-ripples {
154
160
  display: block;
155
161
  position: absolute;
156
162
  top: 0;
@@ -165,7 +171,7 @@ function rippleStyles() {
165
171
  pointer-events: none;
166
172
  }
167
173
 
168
- .zero-ripples.expand {
174
+ .kitzo-ripples.expand {
169
175
  animation: expand-ripple var(--ripples-duration) linear forwards;
170
176
  }
171
177
 
@@ -186,9 +192,9 @@ function rippleStyles() {
186
192
  //! Ripple effect
187
193
  let rippleListenerAdded = false;
188
194
 
189
- function kitzoRipple(element, config = {}) {
195
+ function ripple(element, config = {}) {
190
196
  if (!element) {
191
- console.error('A button element/selector is expected');
197
+ console.error('[kitzo.ripple] A button element/selector is expected');
192
198
  return;
193
199
  }
194
200
 
@@ -208,20 +214,20 @@ function kitzoRipple(element, config = {}) {
208
214
 
209
215
  const allButtons = getButtons(element);
210
216
  if (!allButtons) {
211
- console.error('No elements found for zeroRipple');
217
+ console.error('[kitzo.ripple] No elements found for kitzoRipple');
212
218
  return;
213
219
  }
214
220
  allButtons.forEach((btn) => {
215
- btn.classList.add('zero-ripple');
216
- btn.setAttribute('data-zero-ripple', 'true');
221
+ btn.classList.add('kitzo-ripple');
222
+ btn.setAttribute('data-kitzo-ripple', 'true');
217
223
  });
218
224
 
219
225
  if (!rippleListenerAdded) {
220
226
  document.addEventListener('mousedown', (e) => {
221
- const btn = e.target.closest('[data-zero-ripple]');
227
+ const btn = e.target.closest('[data-kitzo-ripple]');
222
228
  if (btn) {
223
229
  const span = document.createElement('span');
224
- span.className = 'zero-ripples';
230
+ span.className = 'kitzo-ripples';
225
231
  btn.appendChild(span);
226
232
 
227
233
  const { left, top, width } = btn.getBoundingClientRect();
@@ -256,7 +262,7 @@ function tooltipStyles() {
256
262
  }
257
263
  }
258
264
 
259
- .zero-tooltip {
265
+ .kitzo-tooltip {
260
266
  --tooltip-arrow-clr: var(--tooltip-bg-clr);
261
267
 
262
268
  box-sizing: border-box;
@@ -282,42 +288,42 @@ function tooltipStyles() {
282
288
  pointer-events: none;
283
289
  }
284
290
 
285
- .zero-tooltip.show {
291
+ .kitzo-tooltip.show {
286
292
  opacity: 1 !important;
287
293
  }
288
294
 
289
- .zero-tooltip-top::before,
290
- .zero-tooltip-right::before,
291
- .zero-tooltip-bottom::before,
292
- .zero-tooltip-left::before {
295
+ .kitzo-tooltip-top::before,
296
+ .kitzo-tooltip-right::before,
297
+ .kitzo-tooltip-bottom::before,
298
+ .kitzo-tooltip-left::before {
293
299
 
294
300
  content: '';
295
301
  position: absolute;
296
302
  border: 6px solid;
297
303
  }
298
304
 
299
- .zero-tooltip-top::before {
305
+ .kitzo-tooltip-top::before {
300
306
  top: calc(100% - 1px);
301
307
  left: 50%;
302
308
  translate: -50% 0;
303
309
  border-color: var(--tooltip-arrow-clr) transparent transparent transparent;
304
310
  }
305
311
 
306
- .zero-tooltip-right::before {
312
+ .kitzo-tooltip-right::before {
307
313
  top: 50%;
308
314
  right: calc(100% - 1px);
309
315
  translate: 0 -50%;
310
316
  border-color: transparent var(--tooltip-arrow-clr) transparent transparent;
311
317
  }
312
318
 
313
- .zero-tooltip-bottom::before {
319
+ .kitzo-tooltip-bottom::before {
314
320
  bottom: calc(100% - 1px);
315
321
  left: 50%;
316
322
  translate: -50% 0;
317
323
  border-color: transparent transparent var(--tooltip-arrow-clr) transparent;
318
324
  }
319
325
 
320
- .zero-tooltip-left::before {
326
+ .kitzo-tooltip-left::before {
321
327
  left: calc(100% - 1px);
322
328
  top: 50%;
323
329
  translate: 0 -50%;
@@ -330,7 +336,7 @@ let tooltipDiv;
330
336
  let tooltipListenerAdded = false;
331
337
  const tooltipConfigMap = new WeakMap();
332
338
 
333
- function kitzoTooltip(element, config = {}) {
339
+ function tooltip(element, config = {}) {
334
340
  if (window.matchMedia('(pointer: coarse)').matches) return;
335
341
 
336
342
  if (!element) {
@@ -354,20 +360,20 @@ function kitzoTooltip(element, config = {}) {
354
360
 
355
361
  const allButtons = getButtons(element);
356
362
  if (!allButtons) {
357
- console.error('No elements found for zeroTooltip');
363
+ console.error('[kitzo.tooltip] No elements found for kitzoTooltip');
358
364
  return;
359
365
  }
360
366
 
361
367
  const disAllowedStyles = ['top', 'left', 'right', 'bottom', 'position', 'zIndex', 'opacity', 'transform', 'translate', 'scale', 'rotate', 'perspective'];
362
368
  for (const key of disAllowedStyles) {
363
369
  if (key in config.style) {
364
- console.warn(`[zeroTooltip] "${key}" style is managed internally and will be ignored.`);
370
+ console.warn(`[kitzo.tooltip] "${key}" style is managed internally and will be ignored.`);
365
371
  delete config.style[key];
366
372
  }
367
373
  }
368
374
 
369
375
  allButtons.forEach((btn) => {
370
- btn.setAttribute('data-zero-tooltip', true);
376
+ btn.setAttribute('data-kitzo-tooltip', true);
371
377
  tooltipConfigMap.set(btn, config);
372
378
  });
373
379
 
@@ -409,7 +415,7 @@ function kitzoTooltip(element, config = {}) {
409
415
 
410
416
  if (!tooltipListenerAdded) {
411
417
  document.addEventListener('mouseover', (e) => {
412
- const btn = e.target.closest('[data-zero-tooltip]');
418
+ const btn = e.target.closest('[data-kitzo-tooltip]');
413
419
  if (btn) {
414
420
  const { tooltip, direction, offset, customClass, style, arrow } = tooltipConfigMap.get(btn);
415
421
 
@@ -424,7 +430,7 @@ function kitzoTooltip(element, config = {}) {
424
430
 
425
431
  const isArrowOn = arrow === 'on';
426
432
  tooltipDiv.textContent = tooltip;
427
- tooltipDiv.className = `zero-tooltip ${isArrowOn ? `zero-tooltip-${direction}` : ''} ${customClass.trim() ? customClass : ''}`;
433
+ tooltipDiv.className = `kitzo-tooltip ${isArrowOn ? `kitzo-tooltip-${direction}` : ''} ${customClass.trim() ? customClass : ''}`;
428
434
 
429
435
  if (isArrowOn) {
430
436
  const color = getComputedStyle(tooltipDiv).backgroundColor;
@@ -441,7 +447,7 @@ function kitzoTooltip(element, config = {}) {
441
447
  });
442
448
 
443
449
  document.addEventListener('mouseout', (e) => {
444
- const btn = e.target.closest('[data-zero-tooltip]');
450
+ const btn = e.target.closest('[data-kitzo-tooltip]');
445
451
  if (btn) {
446
452
  tooltipDiv.classList.remove('show');
447
453
  }
@@ -451,4 +457,167 @@ function kitzoTooltip(element, config = {}) {
451
457
  }
452
458
  }
453
459
 
454
- export { kitzoCopy, kitzoDebounce, kitzoRipple, kitzoTooltip };
460
+ function clippathStyles() {
461
+ return `.kitzo-clippath-div {
462
+ position: fixed;
463
+ top: 0;
464
+ left: 0;
465
+ width: 0;
466
+ height: 0;
467
+ pointer-events: none;
468
+ opacity: 0;
469
+ clip-path: circle(0 at var(--kitzo-clippath-pos-x) var(--kitzo-clippath-pos-y));
470
+ transition: var(--kitzo-clippath-transition);
471
+ }
472
+
473
+ .kitzo-clippath-div.show {
474
+ opacity: 1;
475
+ clip-path: circle(var(--kitzo-clippath-size) at var(--kitzo-clippath-pos-x) var(--kitzo-clippath-pos-y));
476
+ }`;
477
+ }
478
+
479
+ function getClippathSize(size) {
480
+ if (size?.trim?.() === '') {
481
+ return '20%';
482
+ }
483
+ if (typeof size === 'number') {
484
+ if (size < 0) {
485
+ console.warn("[kitzo.clippath] please provide a string value or positive number(px). Default is '20%'");
486
+ return `20%`;
487
+ }
488
+ return `${size}px`;
489
+ }
490
+ if (typeof size === 'string') {
491
+ return `${size}`;
492
+ }
493
+ console.warn("[kitzo.clippath] please provide a string value or positive number(px). Default is '20%'");
494
+ return '20%';
495
+ }
496
+
497
+ const clippathConfigMap = new WeakMap();
498
+ let isClippathListenersAdded = false;
499
+ let clippathDiv;
500
+
501
+ function clippath(element, config = {}) {
502
+ if (window.matchMedia('(pointer:coarse)').matches) return;
503
+
504
+ if (!element) {
505
+ console.error('[kitzo.clippath] A button element/selector is expected');
506
+ return;
507
+ }
508
+
509
+ addStyleTagToHtmlHead('clippath', clippathStyles());
510
+
511
+ config = Object.assign(
512
+ {
513
+ text: '',
514
+ clippathSize: '20%',
515
+ smooth: true,
516
+ style: {},
517
+ },
518
+ config
519
+ );
520
+
521
+ const allButtons = getButtons(element);
522
+ if (!allButtons) {
523
+ console.error('[kitzo.clippath] No elements found for kitzoTooltip');
524
+ return;
525
+ }
526
+
527
+ const disAllowedStyles = ['top', 'left', 'right', 'bottom', 'position', 'opacity', 'transform', 'translate', 'scale', 'rotate', 'perspective'];
528
+ for (const key of disAllowedStyles) {
529
+ if (key in config.style) {
530
+ console.warn(`[kitzo.clippath] "${key}" style is managed internally and will be ignored.`);
531
+ delete config.style[key];
532
+ }
533
+ }
534
+
535
+ allButtons.forEach((btn) => {
536
+ btn.setAttribute('data-kitzo-clippath', true);
537
+ clippathConfigMap.set(btn, config);
538
+ });
539
+
540
+ if (!clippathDiv) {
541
+ clippathDiv = document.createElement('div');
542
+ clippathDiv.className = 'kitzo-clippath-div';
543
+ document.body.appendChild(clippathDiv);
544
+ }
545
+
546
+ if (!isClippathListenersAdded) {
547
+ let isHovering = false;
548
+
549
+ document.addEventListener('mouseover', (e) => {
550
+ const btn = e.target.closest('[data-kitzo-clippath]');
551
+
552
+ if (btn) {
553
+ isHovering = true;
554
+ const { text, style, clippathSize, smooth } = clippathConfigMap.get(btn);
555
+ const { width, height, top, left } = btn.getBoundingClientRect();
556
+
557
+ clippathDiv.removeAttribute('style');
558
+
559
+ clippathDiv.style.width = width + 'px';
560
+ clippathDiv.style.height = height + 'px';
561
+ clippathDiv.style.top = top + 'px';
562
+ clippathDiv.style.left = left + 'px';
563
+
564
+ if (!text) {
565
+ clippathDiv.innerHTML = btn.innerHTML;
566
+ } else {
567
+ clippathDiv.innerHTML = text;
568
+ }
569
+
570
+ clippathDiv.style.setProperty('--kitzo-clippath-transition', smooth ? 'clip-path 150ms ease-out, opacity 150ms' : 'none');
571
+ clippathDiv.style.setProperty('--kitzo-clippath-size', getClippathSize(clippathSize));
572
+
573
+ const { borderRadius, font, letterSpacing, lineHeight, border, boxSizing, padding } = window.getComputedStyle(btn);
574
+
575
+ Object.assign(clippathDiv.style, {
576
+ backgroundColor: '#01c2b8',
577
+ color: 'white',
578
+ borderRadius,
579
+ font,
580
+ letterSpacing,
581
+ lineHeight,
582
+ border,
583
+ boxSizing,
584
+ padding,
585
+ ...style,
586
+ });
587
+
588
+ requestAnimationFrame(() => {
589
+ clippathDiv.classList.add('show');
590
+ });
591
+ }
592
+ });
593
+
594
+ document.addEventListener('mouseout', (e) => {
595
+ const btn = e.target.closest('[data-kitzo-clippath]');
596
+
597
+ if (btn) {
598
+ clippathDiv.classList.remove('show');
599
+ isHovering = false;
600
+ }
601
+ });
602
+
603
+ document.addEventListener('mousemove', (e) => {
604
+ if (!isHovering) return;
605
+ const btn = e.target.closest('[data-kitzo-clippath]');
606
+
607
+ if (btn) {
608
+ const { top, left } = btn.getBoundingClientRect();
609
+ const localX = e.clientX - left;
610
+ const localY = e.clientY - top;
611
+
612
+ clippathDiv.style.setProperty('--kitzo-clippath-pos-x', `${localX}px`);
613
+ clippathDiv.style.setProperty('--kitzo-clippath-pos-y', `${localY}px`);
614
+ }
615
+ });
616
+
617
+ isClippathListenersAdded = true;
618
+ }
619
+ }
620
+
621
+ const kitzo = { copy, debounce, ripple, tooltip, clippath };
622
+
623
+ export { kitzo as default };
package/dist/kitzo.umd.js CHANGED
@@ -5,6 +5,7 @@
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
7
  //! Helper functions
8
+ // Get elements from dom
8
9
  function getButtons(element) {
9
10
  if (typeof element === 'string') {
10
11
  return document.querySelectorAll(element);
@@ -20,6 +21,7 @@
20
21
  // Add style tags
21
22
  let tooltipStyleAdded = false;
22
23
  let rippleStyleAdded = false;
24
+ let clippathStyleAdded = false;
23
25
 
24
26
  function addStyleTag(styles) {
25
27
  const style = document.createElement('style');
@@ -36,6 +38,10 @@
36
38
  addStyleTag(styles);
37
39
  rippleStyleAdded = true;
38
40
  }
41
+ if (type === 'clippath' && !clippathStyleAdded) {
42
+ addStyleTag(styles);
43
+ clippathStyleAdded = true;
44
+ }
39
45
  }
40
46
 
41
47
  //! Copy function
@@ -108,18 +114,18 @@
108
114
 
109
115
  const allButtons = getButtons(element);
110
116
  if (!allButtons) {
111
- console.error('No elements found for zeroCopy');
117
+ console.error('No elements found for kitzoCopy');
112
118
  return;
113
119
  }
114
120
 
115
121
  if (!allowedEvents.includes(event)) {
116
- console.warn(`[zeroCopy] "${event}" is not allowed. Defaulting to "click".`);
122
+ console.warn(`[kitzo.copy] "${event}" is not allowed. Defaulting to "click".`);
117
123
  }
118
124
 
119
125
  const safeEvent = allowedEvents.includes(event) ? event : 'click';
120
126
 
121
127
  allButtons.forEach((btn) => {
122
- btn.setAttribute('data-zero-copy', 'true');
128
+ btn.setAttribute('data-kitzo-copy', 'true');
123
129
 
124
130
  copyConfigMap.set(btn, {
125
131
  doc,
@@ -129,7 +135,7 @@
129
135
 
130
136
  if (!attachedEvents.has(safeEvent)) {
131
137
  document.addEventListener(safeEvent, (e) => {
132
- const btn = e.target.closest('[data-zero-copy]');
138
+ const btn = e.target.closest('[data-kitzo-copy]');
133
139
  if (!btn) return;
134
140
 
135
141
  const { doc, event } = copyConfigMap.get(btn);
@@ -151,12 +157,12 @@
151
157
  }
152
158
 
153
159
  function rippleStyles() {
154
- return `.zero-ripple {
160
+ return `.kitzo-ripple {
155
161
  position: relative;
156
162
  overflow: hidden;
157
163
  }
158
164
 
159
- .zero-ripples {
165
+ .kitzo-ripples {
160
166
  display: block;
161
167
  position: absolute;
162
168
  top: 0;
@@ -171,7 +177,7 @@
171
177
  pointer-events: none;
172
178
  }
173
179
 
174
- .zero-ripples.expand {
180
+ .kitzo-ripples.expand {
175
181
  animation: expand-ripple var(--ripples-duration) linear forwards;
176
182
  }
177
183
 
@@ -194,7 +200,7 @@
194
200
 
195
201
  function ripple(element, config = {}) {
196
202
  if (!element) {
197
- console.error('A button element/selector is expected');
203
+ console.error('[kitzo.ripple] A button element/selector is expected');
198
204
  return;
199
205
  }
200
206
 
@@ -214,20 +220,20 @@
214
220
 
215
221
  const allButtons = getButtons(element);
216
222
  if (!allButtons) {
217
- console.error('No elements found for zeroRipple');
223
+ console.error('[kitzo.ripple] No elements found for kitzoRipple');
218
224
  return;
219
225
  }
220
226
  allButtons.forEach((btn) => {
221
- btn.classList.add('zero-ripple');
222
- btn.setAttribute('data-zero-ripple', 'true');
227
+ btn.classList.add('kitzo-ripple');
228
+ btn.setAttribute('data-kitzo-ripple', 'true');
223
229
  });
224
230
 
225
231
  if (!rippleListenerAdded) {
226
232
  document.addEventListener('mousedown', (e) => {
227
- const btn = e.target.closest('[data-zero-ripple]');
233
+ const btn = e.target.closest('[data-kitzo-ripple]');
228
234
  if (btn) {
229
235
  const span = document.createElement('span');
230
- span.className = 'zero-ripples';
236
+ span.className = 'kitzo-ripples';
231
237
  btn.appendChild(span);
232
238
 
233
239
  const { left, top, width } = btn.getBoundingClientRect();
@@ -262,7 +268,7 @@
262
268
  }
263
269
  }
264
270
 
265
- .zero-tooltip {
271
+ .kitzo-tooltip {
266
272
  --tooltip-arrow-clr: var(--tooltip-bg-clr);
267
273
 
268
274
  box-sizing: border-box;
@@ -288,42 +294,42 @@
288
294
  pointer-events: none;
289
295
  }
290
296
 
291
- .zero-tooltip.show {
297
+ .kitzo-tooltip.show {
292
298
  opacity: 1 !important;
293
299
  }
294
300
 
295
- .zero-tooltip-top::before,
296
- .zero-tooltip-right::before,
297
- .zero-tooltip-bottom::before,
298
- .zero-tooltip-left::before {
301
+ .kitzo-tooltip-top::before,
302
+ .kitzo-tooltip-right::before,
303
+ .kitzo-tooltip-bottom::before,
304
+ .kitzo-tooltip-left::before {
299
305
 
300
306
  content: '';
301
307
  position: absolute;
302
308
  border: 6px solid;
303
309
  }
304
310
 
305
- .zero-tooltip-top::before {
311
+ .kitzo-tooltip-top::before {
306
312
  top: calc(100% - 1px);
307
313
  left: 50%;
308
314
  translate: -50% 0;
309
315
  border-color: var(--tooltip-arrow-clr) transparent transparent transparent;
310
316
  }
311
317
 
312
- .zero-tooltip-right::before {
318
+ .kitzo-tooltip-right::before {
313
319
  top: 50%;
314
320
  right: calc(100% - 1px);
315
321
  translate: 0 -50%;
316
322
  border-color: transparent var(--tooltip-arrow-clr) transparent transparent;
317
323
  }
318
324
 
319
- .zero-tooltip-bottom::before {
325
+ .kitzo-tooltip-bottom::before {
320
326
  bottom: calc(100% - 1px);
321
327
  left: 50%;
322
328
  translate: -50% 0;
323
329
  border-color: transparent transparent var(--tooltip-arrow-clr) transparent;
324
330
  }
325
331
 
326
- .zero-tooltip-left::before {
332
+ .kitzo-tooltip-left::before {
327
333
  left: calc(100% - 1px);
328
334
  top: 50%;
329
335
  translate: 0 -50%;
@@ -360,20 +366,20 @@
360
366
 
361
367
  const allButtons = getButtons(element);
362
368
  if (!allButtons) {
363
- console.error('No elements found for zeroTooltip');
369
+ console.error('[kitzo.tooltip] No elements found for kitzoTooltip');
364
370
  return;
365
371
  }
366
372
 
367
373
  const disAllowedStyles = ['top', 'left', 'right', 'bottom', 'position', 'zIndex', 'opacity', 'transform', 'translate', 'scale', 'rotate', 'perspective'];
368
374
  for (const key of disAllowedStyles) {
369
375
  if (key in config.style) {
370
- console.warn(`[zeroTooltip] "${key}" style is managed internally and will be ignored.`);
376
+ console.warn(`[kitzo.tooltip] "${key}" style is managed internally and will be ignored.`);
371
377
  delete config.style[key];
372
378
  }
373
379
  }
374
380
 
375
381
  allButtons.forEach((btn) => {
376
- btn.setAttribute('data-zero-tooltip', true);
382
+ btn.setAttribute('data-kitzo-tooltip', true);
377
383
  tooltipConfigMap.set(btn, config);
378
384
  });
379
385
 
@@ -415,7 +421,7 @@
415
421
 
416
422
  if (!tooltipListenerAdded) {
417
423
  document.addEventListener('mouseover', (e) => {
418
- const btn = e.target.closest('[data-zero-tooltip]');
424
+ const btn = e.target.closest('[data-kitzo-tooltip]');
419
425
  if (btn) {
420
426
  const { tooltip, direction, offset, customClass, style, arrow } = tooltipConfigMap.get(btn);
421
427
 
@@ -430,7 +436,7 @@
430
436
 
431
437
  const isArrowOn = arrow === 'on';
432
438
  tooltipDiv.textContent = tooltip;
433
- tooltipDiv.className = `zero-tooltip ${isArrowOn ? `zero-tooltip-${direction}` : ''} ${customClass.trim() ? customClass : ''}`;
439
+ tooltipDiv.className = `kitzo-tooltip ${isArrowOn ? `kitzo-tooltip-${direction}` : ''} ${customClass.trim() ? customClass : ''}`;
434
440
 
435
441
  if (isArrowOn) {
436
442
  const color = getComputedStyle(tooltipDiv).backgroundColor;
@@ -447,7 +453,7 @@
447
453
  });
448
454
 
449
455
  document.addEventListener('mouseout', (e) => {
450
- const btn = e.target.closest('[data-zero-tooltip]');
456
+ const btn = e.target.closest('[data-kitzo-tooltip]');
451
457
  if (btn) {
452
458
  tooltipDiv.classList.remove('show');
453
459
  }
@@ -457,6 +463,168 @@
457
463
  }
458
464
  }
459
465
 
466
+ function clippathStyles() {
467
+ return `.kitzo-clippath-div {
468
+ position: fixed;
469
+ top: 0;
470
+ left: 0;
471
+ width: 0;
472
+ height: 0;
473
+ pointer-events: none;
474
+ opacity: 0;
475
+ clip-path: circle(0 at var(--kitzo-clippath-pos-x) var(--kitzo-clippath-pos-y));
476
+ transition: var(--kitzo-clippath-transition);
477
+ }
478
+
479
+ .kitzo-clippath-div.show {
480
+ opacity: 1;
481
+ clip-path: circle(var(--kitzo-clippath-size) at var(--kitzo-clippath-pos-x) var(--kitzo-clippath-pos-y));
482
+ }`;
483
+ }
484
+
485
+ function getClippathSize(size) {
486
+ if (size?.trim?.() === '') {
487
+ return '20%';
488
+ }
489
+ if (typeof size === 'number') {
490
+ if (size < 0) {
491
+ console.warn("[kitzo.clippath] please provide a string value or positive number(px). Default is '20%'");
492
+ return `20%`;
493
+ }
494
+ return `${size}px`;
495
+ }
496
+ if (typeof size === 'string') {
497
+ return `${size}`;
498
+ }
499
+ console.warn("[kitzo.clippath] please provide a string value or positive number(px). Default is '20%'");
500
+ return '20%';
501
+ }
502
+
503
+ const clippathConfigMap = new WeakMap();
504
+ let isClippathListenersAdded = false;
505
+ let clippathDiv;
506
+
507
+ function clippath(element, config = {}) {
508
+ if (window.matchMedia('(pointer:coarse)').matches) return;
509
+
510
+ if (!element) {
511
+ console.error('[kitzo.clippath] A button element/selector is expected');
512
+ return;
513
+ }
514
+
515
+ addStyleTagToHtmlHead('clippath', clippathStyles());
516
+
517
+ config = Object.assign(
518
+ {
519
+ text: '',
520
+ clippathSize: '20%',
521
+ smooth: true,
522
+ style: {},
523
+ },
524
+ config
525
+ );
526
+
527
+ const allButtons = getButtons(element);
528
+ if (!allButtons) {
529
+ console.error('[kitzo.clippath] No elements found for kitzoTooltip');
530
+ return;
531
+ }
532
+
533
+ const disAllowedStyles = ['top', 'left', 'right', 'bottom', 'position', 'opacity', 'transform', 'translate', 'scale', 'rotate', 'perspective'];
534
+ for (const key of disAllowedStyles) {
535
+ if (key in config.style) {
536
+ console.warn(`[kitzo.clippath] "${key}" style is managed internally and will be ignored.`);
537
+ delete config.style[key];
538
+ }
539
+ }
540
+
541
+ allButtons.forEach((btn) => {
542
+ btn.setAttribute('data-kitzo-clippath', true);
543
+ clippathConfigMap.set(btn, config);
544
+ });
545
+
546
+ if (!clippathDiv) {
547
+ clippathDiv = document.createElement('div');
548
+ clippathDiv.className = 'kitzo-clippath-div';
549
+ document.body.appendChild(clippathDiv);
550
+ }
551
+
552
+ if (!isClippathListenersAdded) {
553
+ let isHovering = false;
554
+
555
+ document.addEventListener('mouseover', (e) => {
556
+ const btn = e.target.closest('[data-kitzo-clippath]');
557
+
558
+ if (btn) {
559
+ isHovering = true;
560
+ const { text, style, clippathSize, smooth } = clippathConfigMap.get(btn);
561
+ const { width, height, top, left } = btn.getBoundingClientRect();
562
+
563
+ clippathDiv.removeAttribute('style');
564
+
565
+ clippathDiv.style.width = width + 'px';
566
+ clippathDiv.style.height = height + 'px';
567
+ clippathDiv.style.top = top + 'px';
568
+ clippathDiv.style.left = left + 'px';
569
+
570
+ if (!text) {
571
+ clippathDiv.innerHTML = btn.innerHTML;
572
+ } else {
573
+ clippathDiv.innerHTML = text;
574
+ }
575
+
576
+ clippathDiv.style.setProperty('--kitzo-clippath-transition', smooth ? 'clip-path 150ms ease-out, opacity 150ms' : 'none');
577
+ clippathDiv.style.setProperty('--kitzo-clippath-size', getClippathSize(clippathSize));
578
+
579
+ const { borderRadius, font, letterSpacing, lineHeight, border, boxSizing, padding } = window.getComputedStyle(btn);
580
+
581
+ Object.assign(clippathDiv.style, {
582
+ backgroundColor: '#01c2b8',
583
+ color: 'white',
584
+ borderRadius,
585
+ font,
586
+ letterSpacing,
587
+ lineHeight,
588
+ border,
589
+ boxSizing,
590
+ padding,
591
+ ...style,
592
+ });
593
+
594
+ requestAnimationFrame(() => {
595
+ clippathDiv.classList.add('show');
596
+ });
597
+ }
598
+ });
599
+
600
+ document.addEventListener('mouseout', (e) => {
601
+ const btn = e.target.closest('[data-kitzo-clippath]');
602
+
603
+ if (btn) {
604
+ clippathDiv.classList.remove('show');
605
+ isHovering = false;
606
+ }
607
+ });
608
+
609
+ document.addEventListener('mousemove', (e) => {
610
+ if (!isHovering) return;
611
+ const btn = e.target.closest('[data-kitzo-clippath]');
612
+
613
+ if (btn) {
614
+ const { top, left } = btn.getBoundingClientRect();
615
+ const localX = e.clientX - left;
616
+ const localY = e.clientY - top;
617
+
618
+ clippathDiv.style.setProperty('--kitzo-clippath-pos-x', `${localX}px`);
619
+ clippathDiv.style.setProperty('--kitzo-clippath-pos-y', `${localY}px`);
620
+ }
621
+ });
622
+
623
+ isClippathListenersAdded = true;
624
+ }
625
+ }
626
+
627
+ exports.clippath = clippath;
460
628
  exports.copy = copy;
461
629
  exports.debounce = debounce;
462
630
  exports.ripple = ripple;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitzo",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "A lightweight JavaScript UI micro-library.",
5
5
  "type": "module",
6
6
  "main": "./dist/kitzo.umd.js",