lapikit 0.4.2 → 0.4.3

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.
@@ -4,6 +4,9 @@ export function ripple(el, options = {}) {
4
4
  const rippleContainer = document.createElement('div');
5
5
  addClasses();
6
6
  setOptions(options);
7
+ function isAriaDisabled() {
8
+ return el.getAttribute('aria-disabled') === 'true';
9
+ }
7
10
  function addClasses(center) {
8
11
  const shouldBeCentered = center || options.center;
9
12
  if (!rippleContainer.classList.contains('kit-ripple--effect')) {
@@ -17,7 +20,7 @@ export function ripple(el, options = {}) {
17
20
  }
18
21
  }
19
22
  function setOptions(options) {
20
- if (options.disabled || el.hasAttribute('aria-disabled')) {
23
+ if (options.disabled || isAriaDisabled()) {
21
24
  rippleContainer.remove();
22
25
  }
23
26
  else {
@@ -37,7 +40,7 @@ export function ripple(el, options = {}) {
37
40
  }
38
41
  }
39
42
  function createRipple(e, center) {
40
- if (options.disabled || el.hasAttribute('aria-disabled')) {
43
+ if (options.disabled || isAriaDisabled()) {
41
44
  return;
42
45
  }
43
46
  if (e instanceof KeyboardEvent) {
@@ -0,0 +1 @@
1
+ export * from './ripple.ts';
@@ -0,0 +1 @@
1
+ export * from "./ripple.js";
@@ -0,0 +1,5 @@
1
+ import type { RippleProps } from '../utils/types/index.ts';
2
+ export declare function ripple(el: HTMLElement, options?: RippleProps): {
3
+ destroy(): void;
4
+ update(newOptions: RippleProps): void;
5
+ };
@@ -0,0 +1,96 @@
1
+ const triggerEvents = ['pointerdown', 'touchstart', 'keydown'];
2
+ const cancelEvents = ['mouseleave', 'dragleave', 'touchmove', 'touchcancel', 'pointerup', 'keyup'];
3
+ export function ripple(el, options = {}) {
4
+ const rippleContainer = document.createElement('div');
5
+ addClasses();
6
+ setOptions(options);
7
+ function isAriaDisabled() {
8
+ return el.getAttribute('aria-disabled') === 'true';
9
+ }
10
+ function addClasses(center) {
11
+ const shouldBeCentered = center || options.center;
12
+ if (!rippleContainer.classList.contains('kit-ripple--effect')) {
13
+ rippleContainer.classList.add('kit-ripple--effect');
14
+ }
15
+ if (!shouldBeCentered && rippleContainer.classList.contains('kit-ripple--center')) {
16
+ rippleContainer.classList.remove('kit-ripple--center');
17
+ }
18
+ if (shouldBeCentered) {
19
+ rippleContainer.classList.add('kit-ripple--center');
20
+ }
21
+ }
22
+ function setOptions(options) {
23
+ if (options.disabled || isAriaDisabled()) {
24
+ rippleContainer.remove();
25
+ }
26
+ else {
27
+ el.appendChild(rippleContainer);
28
+ }
29
+ if (options.duration && options.duration < 0) {
30
+ options.duration = undefined;
31
+ }
32
+ if (options.component) {
33
+ rippleContainer.style.setProperty('--system-ripple-radius', `var(--${options.component}-shape)`);
34
+ }
35
+ if (options.color) {
36
+ rippleContainer.style.setProperty('--system-ripple-color', options.color);
37
+ }
38
+ if (options.duration) {
39
+ rippleContainer.style.setProperty('--system-animation-ripple-duration', `${options.duration}ms`);
40
+ }
41
+ }
42
+ function createRipple(e, center) {
43
+ if (options.disabled || isAriaDisabled()) {
44
+ return;
45
+ }
46
+ if (e instanceof KeyboardEvent) {
47
+ if (!['Enter', 'Space'].includes(e.code) || e.repeat) {
48
+ return;
49
+ }
50
+ e.preventDefault();
51
+ const click = new PointerEvent('pointerdown');
52
+ createRipple(click, true);
53
+ return;
54
+ }
55
+ addClasses(center);
56
+ const rect = el.getBoundingClientRect();
57
+ const clientX = window.TouchEvent && e instanceof TouchEvent
58
+ ? e.touches[0].clientX
59
+ : e.clientX;
60
+ const clientY = window.TouchEvent && e instanceof TouchEvent
61
+ ? e.touches[0].clientY
62
+ : e.clientY;
63
+ const x = clientX - rect.left > el.offsetWidth / 2 ? 0 : el.offsetWidth;
64
+ const y = clientY - rect.top > el.offsetHeight / 2 ? 0 : el.offsetHeight;
65
+ const radius = Math.hypot(x - (clientX - rect.left), y - (clientY - rect.top));
66
+ const ripple = document.createElement('div');
67
+ ripple.classList.add('kit-ripple');
68
+ ripple.style.left = `${clientX - rect.left - radius}px`;
69
+ ripple.style.top = `${clientY - rect.top - radius}px`;
70
+ ripple.style.width = ripple.style.height = `${radius * 2}px`;
71
+ rippleContainer.appendChild(ripple);
72
+ function removeRipple() {
73
+ if (ripple === null) {
74
+ return;
75
+ }
76
+ ripple.style.opacity = '0';
77
+ setTimeout(() => {
78
+ ripple.remove();
79
+ }, options.duration || 1000);
80
+ cancelEvents.forEach((event) => el.removeEventListener(event, removeRipple));
81
+ }
82
+ cancelEvents.forEach((event) => el.addEventListener(event, removeRipple, { passive: true }));
83
+ }
84
+ triggerEvents.forEach((event) => el.addEventListener(event, createRipple, { passive: event === 'touchstart' }));
85
+ return {
86
+ destroy() {
87
+ triggerEvents.forEach((event) => {
88
+ el.removeEventListener(event, createRipple);
89
+ });
90
+ },
91
+ update(newOptions) {
92
+ options = newOptions;
93
+ setOptions(newOptions);
94
+ }
95
+ };
96
+ }
@@ -1,2 +1,2 @@
1
- const lapikitComponents = ['sheet'];
1
+ const lapikitComponents = ['sheet', 'app', 'btn'];
2
2
  export default lapikitComponents;
@@ -0,0 +1,146 @@
1
+ <script lang="ts">
2
+ let { ref = $bindable(), children, ...rest } = $props();
3
+ </script>
4
+
5
+ <div id="kit-app" bind:this={ref} {...rest} class={['kit-application', rest.class]}>
6
+ {@render children?.()}
7
+ </div>
8
+
9
+ <style>
10
+ :root {
11
+ color-scheme: light;
12
+
13
+ --kit-h-neutral: 220;
14
+ --kit-h-success: 145;
15
+ --kit-h-warning: 35;
16
+ --kit-h-danger: 5;
17
+ --kit-h-info: 205;
18
+
19
+ --kit-bg: hsl(0 0% 100%);
20
+ --kit-fg: hsl(222 20% 10%);
21
+ --kit-muted: hsl(220 10% 45%);
22
+
23
+ --kit-surface-1: hsl(0 0% 100%);
24
+ --kit-surface-2: hsl(220 20% 98%);
25
+ --kit-surface-3: hsl(220 18% 94%);
26
+
27
+ --kit-border: hsl(220 16% 88%);
28
+
29
+ --kit-accent: hsl(220 90% 56%);
30
+
31
+ --kit-radius-1: 8px;
32
+ --kit-radius-2: 12px;
33
+ --kit-space-1: 6px;
34
+ --kit-space-2: 10px;
35
+ --kit-space-3: 14px;
36
+
37
+ --kit-focus: hsl(35, 90%, 56%);
38
+
39
+ --kit-disabled-opacity: 0.55;
40
+
41
+ --kit-font:
42
+ ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
43
+ 'Segoe UI Symbol', 'Noto Color Emoji';
44
+ }
45
+
46
+ :root {
47
+ --kit-neutral-bg: color-mix(in oklab, var(--kit-neutral), var(--kit-bg) 85%);
48
+ --kit-neutral-bd: color-mix(in oklab, var(--kit-neutral), var(--kit-border) 70%);
49
+ --kit-neutral-fg: var(--kit-fg);
50
+
51
+ --kit-success-bg: color-mix(in oklab, var(--kit-success), var(--kit-bg) 85%);
52
+ --kit-success-bd: color-mix(in oklab, var(--kit-success), var(--kit-border) 70%);
53
+ --kit-success-fg: var(--kit-fg);
54
+
55
+ --kit-warning-bg: color-mix(in oklab, var(--kit-warning), var(--kit-bg) 85%);
56
+ --kit-warning-bd: color-mix(in oklab, var(--kit-warning), var(--kit-border) 70%);
57
+ --kit-warning-fg: var(--kit-fg);
58
+
59
+ --kit-danger-bg: color-mix(in oklab, var(--kit-danger), var(--kit-bg) 85%);
60
+ --kit-danger-bd: color-mix(in oklab, var(--kit-danger), var(--kit-border) 70%);
61
+ --kit-danger-fg: var(--kit-fg);
62
+
63
+ --kit-info-bg: color-mix(in oklab, var(--kit-info), var(--kit-bg) 85%);
64
+ --kit-info-bd: color-mix(in oklab, var(--kit-info), var(--kit-border) 70%);
65
+ --kit-info-fg: var(--kit-fg);
66
+ }
67
+
68
+ :root {
69
+ --kit-outline-w: 1px;
70
+ --btn-radius: 8px;
71
+
72
+ --kit-btn-gap: 8px;
73
+
74
+ --bg: #111827;
75
+ --fg: #ffffff;
76
+ --bg-hover: #0b1220;
77
+ --border: rgba(255, 255, 255, 0.08);
78
+ --focus: blue;
79
+ --font:
80
+ ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
81
+ 'Segoe UI Symbol', 'Noto Color Emoji';
82
+ }
83
+
84
+ :global(.outline) {
85
+ --container-shape-start-start: var(--btn-radius);
86
+ --container-shape-start-end: var(--btn-radius);
87
+ --container-shape-end-start: var(--btn-radius);
88
+ --container-shape-end-end: var(--btn-radius);
89
+
90
+ border-width: var(--kit-outline-w);
91
+ inset: 0;
92
+ border-style: solid;
93
+ position: absolute;
94
+ box-sizing: border-box;
95
+ border-color: var(--outline-color);
96
+ z-index: 1;
97
+ border-start-start-radius: var(--container-shape-start-start);
98
+ border-start-end-radius: var(--container-shape-start-end);
99
+ border-end-start-radius: var(--container-shape-end-start);
100
+ border-end-end-radius: var(--container-shape-end-end);
101
+ }
102
+
103
+ :global(.kit-ripple) {
104
+ background-color: currentColor;
105
+ opacity: 0.1;
106
+ position: absolute;
107
+ border-radius: 50%;
108
+ pointer-events: none;
109
+ -webkit-transition: 0.6s;
110
+ transition: 0.6s;
111
+ -webkit-animation: animation-l-ripple var(--system-animation-ripple-duration, 0.4s)
112
+ cubic-bezier(0.4, 0, 0.2, 1);
113
+ animation: animation-l-ripple var(--system-animation-ripple-duration, 0.4s)
114
+ cubic-bezier(0.4, 0, 0.2, 1);
115
+ border-radius: var(--system-ripple-radius);
116
+ }
117
+
118
+ :global(.kit-ripple--center) {
119
+ top: 50% !important;
120
+ left: 50% !important;
121
+ translate: -50% -50% !important;
122
+ }
123
+
124
+ :global(.kit-ripple--effect) {
125
+ position: absolute;
126
+ left: 0;
127
+ right: 0;
128
+ top: 0;
129
+ bottom: 0;
130
+ overflow: hidden;
131
+ background: none;
132
+ pointer-events: none;
133
+ z-index: 999;
134
+ border-radius: var(--system-ripple-radius);
135
+ }
136
+
137
+ @keyframes -global-animation-l-ripple {
138
+ from {
139
+ scale: 0;
140
+ }
141
+
142
+ to {
143
+ scale: 1;
144
+ }
145
+ }
146
+ </style>
@@ -0,0 +1,6 @@
1
+ declare const App: import("svelte").Component<{
2
+ ref?: any;
3
+ children: any;
4
+ } & Record<string, any>, {}, "ref">;
5
+ type App = ReturnType<typeof App>;
6
+ export default App;
@@ -0,0 +1,446 @@
1
+ <script lang="ts">
2
+ import { useClassName, useStyles } from '../../utils/index.js';
3
+ import { makeComponentProps } from '../../compiler/mapped-code.js';
4
+ import { ripple } from '../../animations/index.js';
5
+ import type { ButtonProps } from './btn.types.js';
6
+
7
+ let {
8
+ ref = $bindable(),
9
+ is = 'button',
10
+ children,
11
+ class: className = '',
12
+ style: styleAttr = '',
13
+ 's-class': sClass,
14
+ 's-style': sStyle,
15
+ variant = 'filled',
16
+ density = 'default',
17
+ loading,
18
+ active = false,
19
+ size = 'md',
20
+ rounded,
21
+ disabled = false,
22
+ block,
23
+ href,
24
+ input,
25
+ type,
26
+ checked,
27
+ value,
28
+ label,
29
+ wide,
30
+ noRipple,
31
+ ...rest
32
+ }: ButtonProps = $props();
33
+
34
+ let safeVariant = $derived(
35
+ variant === 'filled' || variant === 'outline' || variant === 'text' || variant === 'link'
36
+ ? variant
37
+ : 'filled'
38
+ );
39
+ let safeSize = $derived(
40
+ size === 'xs' || size === 'sm' || size === 'md' || size === 'lg' || size === 'xl' ? size : 'md'
41
+ );
42
+ let safeDensity = $derived(
43
+ density === 'compact' || density === 'comfortable' || density === 'default'
44
+ ? density
45
+ : 'default'
46
+ );
47
+
48
+ let { classProps, styleProps, restProps } = $derived(
49
+ makeComponentProps(rest as Record<string, unknown>)
50
+ );
51
+
52
+ let componentClass = $derived(
53
+ useClassName({
54
+ baseClass: 'kit-btn',
55
+ className: `${className ?? ''} kit-btn--${safeVariant}`.trim(),
56
+ sClass,
57
+ classProps
58
+ })
59
+ );
60
+
61
+ let componentStyle = $derived(
62
+ useStyles({
63
+ styleAttr,
64
+ sStyle,
65
+ styleProps
66
+ })
67
+ );
68
+
69
+ const isInput = $derived(!!input);
70
+ const isDisabled = $derived(!!disabled);
71
+ const tag = $derived((href && 'a') || (isInput && 'input') || is || 'button');
72
+ const inputWrapperTag = $derived(type === 'checkbox' || type === 'radio' ? 'label' : 'div');
73
+ const resolvedHref = $derived(isDisabled ? undefined : href);
74
+ const resolvedDisabled = $derived((tag === 'button' && isDisabled) || undefined);
75
+
76
+ const resolvedType = $derived(() => {
77
+ if (tag !== 'button') return type;
78
+ return type ?? 'button';
79
+ });
80
+ </script>
81
+
82
+ {#if isInput}
83
+ <svelte:element
84
+ this={inputWrapperTag}
85
+ bind:this={ref}
86
+ class={componentClass}
87
+ style={componentStyle}
88
+ data-size={safeSize}
89
+ data-variant={safeVariant}
90
+ data-loading={loading}
91
+ data-active={active}
92
+ data-disabled={isDisabled}
93
+ data-density={safeDensity}
94
+ data-rounded={rounded}
95
+ aria-busy={disabled}
96
+ aria-disabled={isDisabled || undefined}
97
+ data-block={block}
98
+ data-wide={wide}
99
+ use:ripple={{
100
+ component: 'btn',
101
+ disabled: noRipple || disabled
102
+ }}
103
+ >
104
+ {#if safeVariant === 'outline'}
105
+ <span class="outline"></span>
106
+ {/if}
107
+ <input
108
+ {...restProps}
109
+ type={type || 'button'}
110
+ {checked}
111
+ {value}
112
+ aria-label={String(label || value)}
113
+ disabled={isDisabled}
114
+ />
115
+ {#if loading}
116
+ <span class="spinner">...</span>
117
+ {/if}
118
+ </svelte:element>
119
+ {:else}
120
+ <svelte:element
121
+ this={tag}
122
+ bind:this={ref}
123
+ class={componentClass}
124
+ style={componentStyle}
125
+ {...restProps}
126
+ type={resolvedType()}
127
+ href={resolvedHref}
128
+ data-size={safeSize}
129
+ data-variant={safeVariant}
130
+ data-loading={loading}
131
+ data-active={active}
132
+ data-disabled={isDisabled}
133
+ data-density={safeDensity}
134
+ data-rounded={rounded}
135
+ disabled={resolvedDisabled}
136
+ aria-busy={disabled}
137
+ aria-disabled={isDisabled || undefined}
138
+ data-block={block}
139
+ data-wide={wide}
140
+ use:ripple={{
141
+ component: 'btn',
142
+ disabled: noRipple || disabled
143
+ }}
144
+ >
145
+ {#if safeVariant === 'outline'}
146
+ <span class="outline"></span>
147
+ {/if}
148
+
149
+ <span class="kit-btn__inner">
150
+ <span class="kit-btn__content">
151
+ {@render children?.()}
152
+ </span>
153
+ </span>
154
+
155
+ {#if loading}
156
+ <span class="spinner">...</span>
157
+ {/if}
158
+ </svelte:element>
159
+ {/if}
160
+
161
+ <style>
162
+ input {
163
+ border: 0;
164
+ padding: 0;
165
+ background: transparent;
166
+ color: inherit;
167
+ cursor: pointer;
168
+ }
169
+ /* typography consistency */
170
+ button,
171
+ input,
172
+ select,
173
+ textarea {
174
+ font: inherit;
175
+ color: inherit;
176
+ }
177
+
178
+ /* remove native button styles */
179
+ button {
180
+ appearance: none;
181
+ background: none;
182
+ border: none;
183
+ }
184
+
185
+ .kit-btn {
186
+ --kit-btn-bg: var(--kit-surface-2);
187
+ --kit-btn-fg: var(--kit-fg);
188
+ --kit-btn-bd: var(--kit-border);
189
+ --kit-btn-bg--hover: color-mix(in oklab, var(--kit-btn-bg), var(--kit-fg) 6%);
190
+ --kit-btn-bg--active: color-mix(in oklab, var(--kit-btn-bg), var(--kit-fg) 10%);
191
+ --kit-btn-bd--hover: color-mix(in oklab, var(--kit-btn-bd), var(--kit-fg) 12%);
192
+ --kit-btn-font: var(--kit-font);
193
+ --kit-btn-h-xs: 28px;
194
+ --kit-btn-h-sm: 32px;
195
+ --kit-btn-h-md: 40px;
196
+ --kit-btn-h-lg: 48px;
197
+ --kit-btn-h-xl: 56px;
198
+ --kit-btn-px-xs: 10px;
199
+ --kit-btn-px-sm: 12px;
200
+ --kit-btn-px-md: 16px;
201
+ --kit-btn-px-lg: 20px;
202
+ --kit-btn-px-xl: 24px;
203
+ --btn-density-scale: 1;
204
+ --btn-density-height-scale: 1;
205
+ --btn-radius: 8px;
206
+ --btn-shape: var(--btn-radius);
207
+
208
+ position: relative;
209
+ display: inline-flex;
210
+ box-sizing: border-box;
211
+ align-items: center;
212
+ justify-content: center;
213
+ font-family: var(--kit-btn-font);
214
+ background: var(--btn-bg);
215
+ color: var(--btn-fg);
216
+ height: max(28px, calc(var(--btn-h) * var(--btn-density-height-scale)));
217
+ padding-inline: calc(var(--btn-px) * var(--btn-density-scale));
218
+ border-radius: var(--btn-radius);
219
+ text-decoration: none;
220
+ white-space: nowrap;
221
+ user-select: none;
222
+ cursor: pointer;
223
+ border: 0;
224
+ transition:
225
+ background 150ms ease,
226
+ transform 50ms ease;
227
+ }
228
+
229
+ .kit-btn:hover {
230
+ background: var(--btn-hover-bg);
231
+ color: var(--btn-hover-fg);
232
+ text-decoration: var(--btn-decoration);
233
+ }
234
+
235
+ .kit-btn:has(> :is(input[type='checkbox'], input[type='radio']):checked) {
236
+ background: var(--btn-active-bg);
237
+ color: var(--btn-active-fg);
238
+ text-decoration: var(--btn-decoration);
239
+ }
240
+
241
+ .kit-btn:has(> :is(input[type='checkbox'], input[type='radio']):checked):hover {
242
+ background: var(--btn-hover-bg);
243
+ color: var(--btn-hover-fg);
244
+ text-decoration: var(--btn-decoration);
245
+ }
246
+
247
+ .kit-btn:active,
248
+ .kit-btn[data-active='true'] {
249
+ background: var(--btn-active-bg);
250
+ color: var(--btn-active-fg);
251
+ text-decoration: var(--btn-decoration);
252
+ transform: translateY(1px);
253
+ }
254
+
255
+ .kit-btn[data-active='true']:hover {
256
+ background: var(--btn-hover-bg);
257
+ color: var(--btn-hover-fg);
258
+ text-decoration: var(--btn-decoration);
259
+ }
260
+
261
+ :is(.kit-btn:focus-visible, .kit-btn:has(> input:focus-visible)) {
262
+ outline: 2px solid var(--kit-focus);
263
+ outline-offset: 2px;
264
+ }
265
+
266
+ .kit-btn > input:focus-visible {
267
+ outline: none;
268
+ box-shadow: none;
269
+ }
270
+
271
+ .kit-btn > :is(input[type='checkbox'], input[type='radio']) {
272
+ appearance: none;
273
+ margin: 0;
274
+ cursor: pointer;
275
+ }
276
+
277
+ .kit-btn > :is(input[type='checkbox'], input[type='radio']):after {
278
+ --btn-content: attr(aria-label);
279
+ content: var(--btn-content);
280
+ cursor: pointer;
281
+ }
282
+
283
+ /* variant */
284
+ .kit-btn[data-variant='filled'] {
285
+ /* default style*/
286
+ --btn-bg: var(--kit-accent);
287
+ --btn-fg: white;
288
+ --btn-hover-bg: color-mix(in oklab, var(--kit-accent), black 10%);
289
+ --btn-hover-fg: var(--btn-fg);
290
+ --btn-active-bg: color-mix(in oklab, var(--kit-accent), black 16%);
291
+ --btn-active-fg: var(--btn-fg);
292
+ }
293
+
294
+ .kit-btn[data-variant='outline'] {
295
+ --outline-color: var(--kit-accent);
296
+ }
297
+
298
+ .kit-btn[data-variant='outline'],
299
+ .kit-btn[data-variant='text'] {
300
+ --btn-bg: transparent;
301
+ --btn-fg: var(--kit-accent);
302
+ --btn-hover-bg: color-mix(in oklab, var(--kit-accent), transparent 80%);
303
+ --btn-hover-fg: var(--btn-fg);
304
+ --btn-active-bg: color-mix(in oklab, var(--kit-accent), transparent 92%);
305
+ --btn-active-fg: var(--btn-fg);
306
+ }
307
+
308
+ .kit-btn[data-variant='link'] {
309
+ --btn-bg: transparent;
310
+ --btn-fg: var(--kit-accent);
311
+ --btn-hover-fg: var(--btn-fg);
312
+ --btn-active-fg: var(--btn-fg);
313
+ --btn-decoration: underline;
314
+ height: inherit;
315
+ padding: 0;
316
+ }
317
+
318
+ /* size */
319
+ .kit-btn[data-size='xs'] {
320
+ --btn-h: var(--kit-btn-h-xs);
321
+ --btn-height: var(--kit-btn-h-xs);
322
+ --btn-px: var(--kit-btn-px-xs);
323
+ font-size: 12px;
324
+ }
325
+
326
+ .kit-btn[data-size='sm'] {
327
+ --btn-h: var(--kit-btn-h-sm);
328
+ --btn-height: var(--kit-btn-h-sm);
329
+ --btn-px: var(--kit-btn-px-sm);
330
+ font-size: 13px;
331
+ }
332
+
333
+ .kit-btn[data-size='md'] {
334
+ --btn-h: var(--kit-btn-h-md);
335
+ --btn-height: var(--kit-btn-h-md);
336
+ --btn-px: var(--kit-btn-px-md);
337
+ font-size: 14px;
338
+ }
339
+
340
+ .kit-btn[data-size='lg'] {
341
+ --btn-h: var(--kit-btn-h-lg);
342
+ --btn-height: var(--kit-btn-h-lg);
343
+ --btn-px: var(--kit-btn-px-lg);
344
+ font-size: 15px;
345
+ }
346
+
347
+ .kit-btn[data-size='xl'] {
348
+ --btn-h: var(--kit-btn-h-xl);
349
+ --btn-height: var(--kit-btn-h-xl);
350
+ --btn-px: var(--kit-btn-px-xl);
351
+ font-size: 16px;
352
+ }
353
+
354
+ /* density */
355
+ .kit-btn[data-density='default'] {
356
+ --btn-density-scale: 1;
357
+ --btn-density-height-scale: 1;
358
+ }
359
+
360
+ .kit-btn[data-density='compact'] {
361
+ --btn-density-scale: 0.9;
362
+ --btn-density-height-scale: 0.92;
363
+ }
364
+
365
+ .kit-btn[data-density='comfortable'] {
366
+ --btn-density-scale: 1.1;
367
+ --btn-density-height-scale: 1.08;
368
+ }
369
+
370
+ /* rounded */
371
+ .kit-btn[data-rounded='0'] {
372
+ --btn-radius: 0;
373
+ }
374
+
375
+ .kit-btn[data-rounded='xs'] {
376
+ --btn-radius: 2px;
377
+ }
378
+
379
+ .kit-btn[data-rounded='sm'] {
380
+ --btn-radius: 4px;
381
+ }
382
+
383
+ .kit-btn[data-rounded='md'] {
384
+ --btn-radius: 8px;
385
+ }
386
+
387
+ .kit-btn[data-rounded='lg'] {
388
+ --btn-radius: 16px;
389
+ }
390
+
391
+ .kit-btn[data-rounded='xl'] {
392
+ --btn-radius: 99999px;
393
+ }
394
+
395
+ .kit-btn[data-wide='true'] {
396
+ width: 100%;
397
+ max-width: 16rem;
398
+ }
399
+
400
+ .kit-btn .outline {
401
+ pointer-events: none;
402
+ }
403
+
404
+ .kit-btn__inner {
405
+ display: flex;
406
+ align-items: center;
407
+ gap: var(--kit-btn-gap);
408
+ }
409
+
410
+ .kit-btn[data-loading='true'] .kit-btn__inner,
411
+ .kit-btn[data-loading='true'] input {
412
+ opacity: 0;
413
+ }
414
+
415
+ .kit-btn[data-loading='true'] {
416
+ pointer-events: none;
417
+ user-select: none;
418
+ cursor: pointer;
419
+ }
420
+
421
+ .spinner {
422
+ position: absolute;
423
+ inset: 0;
424
+ display: flex;
425
+ align-items: center;
426
+ justify-content: center;
427
+ }
428
+
429
+ .kit-btn[data-block='true'] {
430
+ display: flex;
431
+ width: 100%;
432
+ }
433
+
434
+ .kit-btn[data-disabled='true'] {
435
+ pointer-events: none;
436
+ background: color-mix(in oklab, var(--btn-bg), transparent 70%);
437
+ color: color-mix(in oklab, var(--btn-fg), transparent 45%);
438
+
439
+ user-select: none;
440
+ cursor: not-allowed;
441
+ }
442
+
443
+ .kit-btn[data-disabled='true'] > input {
444
+ cursor: not-allowed;
445
+ }
446
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { ButtonProps } from './btn.types.ts';
2
+ declare const Btn: import("svelte").Component<ButtonProps, {}, "ref">;
3
+ type Btn = ReturnType<typeof Btn>;
4
+ export default Btn;
@@ -0,0 +1,21 @@
1
+ import type { Component, RoundedType, SizeType } from '../../utils/types/index.js';
2
+ export interface ButtonProps extends Component {
3
+ ref?: HTMLElement | null;
4
+ is?: 'button' | 'a' | 'input';
5
+ input?: boolean;
6
+ href?: string;
7
+ variant?: 'outline' | 'text' | 'filled' | 'link';
8
+ density?: 'compact' | 'comfortable' | 'default';
9
+ active?: boolean;
10
+ loading?: boolean;
11
+ disabled?: boolean;
12
+ checked?: boolean;
13
+ size?: SizeType;
14
+ rounded?: RoundedType;
15
+ type?: 'button' | 'submit' | 'reset' | 'checkbox' | 'radio';
16
+ value?: string | number | boolean;
17
+ label?: string;
18
+ block?: boolean;
19
+ wide?: boolean;
20
+ noRipple?: boolean;
21
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1,3 @@
1
1
  export { default as KitSheet } from './sheet/sheet.svelte';
2
+ export { default as KitApp } from './app/app.svelte';
3
+ export { default as KitBtn } from './btn/btn.svelte';
@@ -1,2 +1,4 @@
1
1
  // components
2
2
  export { default as KitSheet } from './sheet/sheet.svelte';
3
+ export { default as KitApp } from './app/app.svelte';
4
+ export { default as KitBtn } from './btn/btn.svelte';
@@ -1,5 +1,13 @@
1
+ import type { Snippet } from 'svelte';
1
2
  import type { SClassProp, SStyleProp } from '../../compiler/types/index.js';
3
+ type IdElementType = string | undefined;
4
+ type ClassNameType = string | string[] | undefined;
5
+ type KitClassNameType = string | string[] | undefined;
6
+ type KitStylePropertiesType = Record<string, boolean | string> | undefined;
7
+ type StylePropertiesType = string | undefined;
2
8
  export type PropValue = string | boolean | number | null | undefined;
9
+ export type SizeType = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
10
+ export type RoundedType = 0 | '0' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
3
11
  export interface useClassNameProps {
4
12
  baseClass?: string;
5
13
  className?: string;
@@ -11,3 +19,22 @@ export interface useStylesProps {
11
19
  sStyle?: SStyleProp;
12
20
  styleProps?: Record<string, PropValue>;
13
21
  }
22
+ export interface Base {
23
+ id?: IdElementType;
24
+ class?: ClassNameType;
25
+ style?: StylePropertiesType;
26
+ 's-class'?: KitClassNameType;
27
+ 's-style'?: KitStylePropertiesType;
28
+ [key: string]: any;
29
+ }
30
+ export interface Component extends Base {
31
+ children?: Snippet;
32
+ }
33
+ export interface RippleProps {
34
+ component?: string;
35
+ center?: boolean;
36
+ color?: string;
37
+ duration?: number;
38
+ disabled?: boolean;
39
+ }
40
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lapikit",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"