lapikit 0.6.10 → 0.6.12

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.
@@ -10,41 +10,49 @@ function getCoords(e) {
10
10
  return { x: e.clientX, y: e.clientY };
11
11
  }
12
12
  export function ripple(el, options = {}) {
13
- const rippleContainer = document.createElement('div');
13
+ // created on first interaction, removed once every ripple has faded out
14
+ let rippleContainer;
14
15
  const activeRipples = new Set();
15
- addClasses();
16
- setOptions(options);
17
16
  function isAriaDisabled() {
18
17
  return el.getAttribute('aria-disabled') === 'true';
19
18
  }
20
- function addClasses(center) {
21
- const shouldBeCentered = center || options.center;
22
- if (!rippleContainer.classList.contains('kit-ripple--effect')) {
23
- rippleContainer.classList.add('kit-ripple--effect');
19
+ function applyOptions(container) {
20
+ if (options.component) {
21
+ container.style.setProperty('--system-ripple-radius', `var(--kit-${options.component}-radius)`);
24
22
  }
25
- if (!shouldBeCentered && rippleContainer.classList.contains('kit-ripple--center')) {
26
- rippleContainer.classList.remove('kit-ripple--center');
23
+ if (options.color) {
24
+ container.style.setProperty('--system-ripple-color', options.color);
27
25
  }
28
- if (shouldBeCentered) {
29
- rippleContainer.classList.add('kit-ripple--center');
26
+ const duration = resolveDuration(options);
27
+ if (duration) {
28
+ container.style.setProperty('--system-animation-ripple-duration', `${duration}ms`);
30
29
  }
31
30
  }
32
- function setOptions(newOptions) {
33
- if (newOptions.disabled || isAriaDisabled()) {
34
- rippleContainer.remove();
31
+ function mountContainer(center) {
32
+ if (!rippleContainer) {
33
+ rippleContainer = document.createElement('div');
34
+ rippleContainer.classList.add('kit-ripple--effect');
35
+ applyOptions(rippleContainer);
35
36
  }
36
- else {
37
+ rippleContainer.classList.toggle('kit-ripple--center', !!(center || options.center));
38
+ if (!rippleContainer.isConnected) {
37
39
  el.appendChild(rippleContainer);
38
40
  }
39
- if (newOptions.component) {
40
- rippleContainer.style.setProperty('--system-ripple-radius', `var(--kit-${newOptions.component}-radius)`);
41
- }
42
- if (newOptions.color) {
43
- rippleContainer.style.setProperty('--system-ripple-color', newOptions.color);
41
+ return rippleContainer;
42
+ }
43
+ function unmountContainer() {
44
+ rippleContainer?.remove();
45
+ rippleContainer = undefined;
46
+ }
47
+ function setOptions(newOptions) {
48
+ options = newOptions;
49
+ if (newOptions.disabled || isAriaDisabled()) {
50
+ activeRipples.forEach((cleanup) => cleanup());
51
+ activeRipples.clear();
52
+ unmountContainer();
44
53
  }
45
- const duration = resolveDuration(newOptions);
46
- if (duration) {
47
- rippleContainer.style.setProperty('--system-animation-ripple-duration', `${duration}ms`);
54
+ else if (rippleContainer) {
55
+ applyOptions(rippleContainer);
48
56
  }
49
57
  }
50
58
  function createRipple(e, center) {
@@ -60,7 +68,7 @@ export function ripple(el, options = {}) {
60
68
  createRipple(click, true);
61
69
  return;
62
70
  }
63
- addClasses(center);
71
+ const container = mountContainer(center);
64
72
  const rect = el.getBoundingClientRect();
65
73
  const { x: clientX, y: clientY } = getCoords(e);
66
74
  const x = clientX - rect.left > el.offsetWidth / 2 ? 0 : el.offsetWidth;
@@ -71,7 +79,7 @@ export function ripple(el, options = {}) {
71
79
  ripple.style.left = `${clientX - rect.left - radius}px`;
72
80
  ripple.style.top = `${clientY - rect.top - radius}px`;
73
81
  ripple.style.width = ripple.style.height = `${radius * 2}px`;
74
- rippleContainer.appendChild(ripple);
82
+ container.appendChild(ripple);
75
83
  let timeoutId;
76
84
  function cleanup() {
77
85
  if (timeoutId) {
@@ -80,12 +88,18 @@ export function ripple(el, options = {}) {
80
88
  cancelEvents.forEach((event) => el.removeEventListener(event, removeRipple));
81
89
  ripple.remove();
82
90
  }
91
+ function release() {
92
+ activeRipples.delete(cleanup);
93
+ if (activeRipples.size === 0) {
94
+ unmountContainer();
95
+ }
96
+ }
83
97
  function removeRipple() {
84
98
  ripple.style.opacity = '0';
85
99
  cancelEvents.forEach((event) => el.removeEventListener(event, removeRipple));
86
100
  timeoutId = setTimeout(() => {
87
101
  ripple.remove();
88
- activeRipples.delete(cleanup);
102
+ release();
89
103
  }, resolveDuration(options) || 1000);
90
104
  }
91
105
  activeRipples.add(cleanup);
@@ -99,10 +113,9 @@ export function ripple(el, options = {}) {
99
113
  });
100
114
  activeRipples.forEach((cleanup) => cleanup());
101
115
  activeRipples.clear();
102
- rippleContainer.remove();
116
+ unmountContainer();
103
117
  },
104
118
  update(newOptions) {
105
- options = newOptions;
106
119
  setOptions(newOptions);
107
120
  }
108
121
  };
@@ -63,10 +63,6 @@
63
63
  let activatorRef = $state<HTMLElement | PointerEvent | null>(null);
64
64
  let open = $state(false);
65
65
  let axis = $state(positioner.values);
66
- let innerHeight = $state(0);
67
- let innerWidth = $state(0);
68
- let scrollX = $state(0);
69
- let scrollY = $state(0);
70
66
  let timeoutId = $state<ReturnType<typeof setTimeout> | null>(null);
71
67
 
72
68
  const clearHoverTimeout = () => {
@@ -131,18 +127,17 @@
131
127
  });
132
128
 
133
129
  $effect(() => {
134
- if (
135
- open &&
136
- contentRef &&
137
- activatorRef &&
138
- (scrollX > 0 || scrollY > 0 || innerHeight > 0 || innerWidth > 0)
139
- ) {
140
- updatePosition();
141
- }
142
- });
130
+ if (!open) return;
143
131
 
144
- $effect(() => {
145
- if (scrollX || scrollY) open = false;
132
+ const close = () => (open = false);
133
+
134
+ window.addEventListener('scroll', close, { passive: true });
135
+ window.addEventListener('resize', updatePosition);
136
+
137
+ return () => {
138
+ window.removeEventListener('scroll', close);
139
+ window.removeEventListener('resize', updatePosition);
140
+ };
146
141
  });
147
142
 
148
143
  $effect(() => {
@@ -154,8 +149,6 @@
154
149
  });
155
150
  </script>
156
151
 
157
- <svelte:window bind:innerHeight bind:innerWidth bind:scrollX bind:scrollY />
158
-
159
152
  {@render activator?.(model, (state, element) => handleMouseEvent(state, element))}
160
153
 
161
154
  {#if open}
@@ -158,9 +158,15 @@
158
158
  --kit-list-item-hover-bg: color-mix(in oklab, var(--kit-list-item-fg), transparent 80%);
159
159
  --kit-list-item-active-bg: color-mix(in oklab, var(--kit-list-item-fg), transparent 92%);
160
160
  }
161
- .kit-list[data-variant='text'] :global(.kit-list-item .outline),
162
- .kit-list[data-variant='filled'] :global(.kit-list-item .outline) {
163
- display: none;
161
+ .kit-list[data-variant='outline'] :global(.kit-list-item::before) {
162
+ content: '';
163
+ position: absolute;
164
+ inset: 0;
165
+ border: 1px solid var(--kit-list-item-bd);
166
+ border-radius: inherit;
167
+ box-sizing: border-box;
168
+ z-index: 1;
169
+ pointer-events: none;
164
170
  }
165
171
 
166
172
  /**
@@ -81,7 +81,6 @@
81
81
  }}
82
82
  {...restProps}
83
83
  >
84
- <span class="outline"></span>
85
84
  {#if prepend}
86
85
  <span class="kit-list-item__prepend">
87
86
  {@render prepend?.()}
@@ -189,8 +188,4 @@
189
188
  text-overflow: ellipsis;
190
189
  white-space: nowrap;
191
190
  }
192
-
193
- .kit-list-item .outline {
194
- --outline-color: var(--kit-list-item-bd);
195
- }
196
191
  </style>
@@ -50,10 +50,6 @@
50
50
  let contentRef = $state<HTMLElement | null>(null);
51
51
  let activatorRef = $state<HTMLElement | null>(null);
52
52
  let axis = $state(positioner.values);
53
- let innerHeight = $state(0);
54
- let innerWidth = $state(0);
55
- let scrollX = $state(0);
56
- let scrollY = $state(0);
57
53
 
58
54
  const handleToggle = (element: HTMLElement | null) => {
59
55
  if (element === null) return;
@@ -78,18 +74,17 @@
78
74
  });
79
75
 
80
76
  $effect(() => {
81
- if (
82
- open &&
83
- contentRef &&
84
- activatorRef &&
85
- (scrollX > 0 || scrollY > 0 || innerHeight > 0 || innerWidth > 0)
86
- ) {
87
- updatePosition();
88
- }
89
- });
77
+ if (!open) return;
90
78
 
91
- $effect(() => {
92
- if (scrollX || scrollY) open = false;
79
+ const close = () => (open = false);
80
+
81
+ window.addEventListener('scroll', close, { passive: true });
82
+ window.addEventListener('resize', updatePosition);
83
+
84
+ return () => {
85
+ window.removeEventListener('scroll', close);
86
+ window.removeEventListener('resize', updatePosition);
87
+ };
93
88
  });
94
89
 
95
90
  $effect(() => {
@@ -107,8 +102,6 @@
107
102
  );
108
103
  </script>
109
104
 
110
- <svelte:window bind:innerHeight bind:innerWidth bind:scrollX bind:scrollY />
111
-
112
105
  {@render activator?.(model)}
113
106
 
114
107
  {#if open}
@@ -72,10 +72,6 @@
72
72
  let tooltipRef = $state<HTMLElement | null>(null);
73
73
  let axis = $state(positioner.values);
74
74
  let timer = $state<ReturnType<typeof setTimeout> | null>(null);
75
- let innerHeight = $state(0);
76
- let innerWidth = $state(0);
77
- let scrollX = $state(0);
78
- let scrollY = $state(0);
79
75
  const tooltipId = `kit-tooltip-${Math.random().toString(36).slice(2, 10)}`;
80
76
 
81
77
  const clearTimer = () => {
@@ -138,14 +134,15 @@
138
134
  });
139
135
 
140
136
  $effect(() => {
141
- if (
142
- open &&
143
- triggerRef &&
144
- tooltipRef &&
145
- (scrollX > 0 || scrollY > 0 || innerHeight > 0 || innerWidth > 0)
146
- ) {
147
- updatePosition();
148
- }
137
+ if (!open) return;
138
+
139
+ window.addEventListener('scroll', updatePosition, { passive: true });
140
+ window.addEventListener('resize', updatePosition);
141
+
142
+ return () => {
143
+ window.removeEventListener('scroll', updatePosition);
144
+ window.removeEventListener('resize', updatePosition);
145
+ };
149
146
  });
150
147
 
151
148
  $effect(() => {
@@ -157,8 +154,6 @@
157
154
  });
158
155
  </script>
159
156
 
160
- <svelte:window bind:innerHeight bind:innerWidth bind:scrollX bind:scrollY />
161
-
162
157
  <!-- svelte-ignore a11y_no_static_element_interactions -->
163
158
  <span
164
159
  bind:this={triggerRef}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lapikit",
3
- "version": "0.6.10",
3
+ "version": "0.6.12",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"