lapikit 0.2.0 → 0.2.1

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.
@@ -1,23 +1,24 @@
1
+ /* root */
1
2
  .kit-alert {
2
3
  --alert-color: var(--on, var(--kit-on-container));
3
4
  --alert-background: var(--base, var(--kit-container));
4
5
  --alert-radius: var(--shape, var(--kit-radius-md));
6
+ }
5
7
 
8
+ .kit-alert {
6
9
  display: grid;
7
10
  flex: 1 1;
8
11
  grid-template-areas:
9
12
  'prepend content append close'
10
13
  '. content . .';
11
- /* grid-template-columns: max-content auto max-content max-content; */ /* bug */
14
+ grid-template-columns: max-content minmax(0, 1fr) max-content max-content;
12
15
  position: relative;
13
16
  padding: 1rem;
14
17
  overflow: hidden;
15
18
  color: var(--alert-color);
16
19
  background-color: var(--alert-background);
17
20
  border-radius: var(--alert-radius);
18
- /* transition:
19
- color 0.5s,
20
- background-color 0.5s; */
21
+ line-height: 0;
21
22
  }
22
23
 
23
24
  .kit-alert .kit-alert--underlay {
@@ -53,7 +54,7 @@
53
54
  padding-top: 0.75rem;
54
55
  }
55
56
 
56
- .kit-alert .kit-alert-prepend {
57
+ .kit-alert .kit-alert--prepend {
57
58
  align-self: flex-start;
58
59
  display: flex;
59
60
  align-items: center;
@@ -61,8 +62,8 @@
61
62
  margin-inline-end: 1rem;
62
63
  }
63
64
 
64
- .kit-alert .kit-alert-content {
65
- align-self: center;
65
+ .kit-alert .kit-alert--content {
66
+ align-self: flex-start;
66
67
  grid-area: content;
67
68
  overflow: hidden;
68
69
  }
@@ -74,6 +75,14 @@
74
75
  grid-area: close;
75
76
  }
76
77
 
78
+ .kit-alert .kit-alert--append {
79
+ align-self: flex-start;
80
+ display: flex;
81
+ align-items: center;
82
+ grid-area: append;
83
+ margin-inline-start: 1rem;
84
+ }
85
+
77
86
  /* state */
78
87
  .kit-alert.kit-alert--info:not([class*='alert--variant-']) {
79
88
  --on: var(--kit-on-info);
@@ -147,8 +147,8 @@
147
147
  }
148
148
 
149
149
  .kit-button[breakpoint]kit-button--variant-outline {
150
- --button-color: var(--base, var(--kit-on-container));
151
- background-color: transparent;
150
+ --button-color: var(--on, var(--kit-on-container));
151
+ background-color: var(--button-background);
152
152
  }
153
153
  .kit-button[breakpoint]kit-button--variant-outline::before {
154
154
  content: '';
@@ -36,6 +36,7 @@
36
36
  white-space: nowrap;
37
37
  gap: calc(var(--kit-spacing) * var(--chip-multiplier-gap));
38
38
  font-size: calc(var(--kit-spacing) * var(--chip-multiplier-font-size));
39
+ line-height: 0;
39
40
  }
40
41
 
41
42
  .kit-chip:not(div):not(span)::after {
@@ -115,8 +116,8 @@
115
116
  }
116
117
 
117
118
  .kit-chip[breakpoint]kit-chip--variant-outline {
118
- --chip-color: var(--base, var(--kit-oncontainer));
119
- background-color: transparent;
119
+ --chip-color: var(--on, var(--kit-on-container));
120
+ background-color: var(--chip-background);
120
121
  }
121
122
  .kit-chip[breakpoint]kit-chip--variant-outline::before {
122
123
  content: '';
@@ -19,3 +19,4 @@ export { default as Card } from './card/card.svelte';
19
19
  export { default as Toolbar } from './toolbar/toolbar.svelte';
20
20
  export { default as Appbar } from './appbar/appbar.svelte';
21
21
  export { default as Spacer } from './spacer/spacer.svelte';
22
+ export { default as Textfield } from './textfield/textfield.svelte';
@@ -20,3 +20,4 @@ export { default as Card } from './card/card.svelte';
20
20
  export { default as Toolbar } from './toolbar/toolbar.svelte';
21
21
  export { default as Appbar } from './appbar/appbar.svelte';
22
22
  export { default as Spacer } from './spacer/spacer.svelte';
23
+ export { default as Textfield } from './textfield/textfield.svelte';
@@ -0,0 +1,305 @@
1
+ /* root */
2
+ .kit-textfield {
3
+ --textfield-color: var(--on, var(--kit-on-container));
4
+ --textfield-background: var(--base, var(--kit-container));
5
+ --textfield-radius: var(--shape, var(--kit-radius-md));
6
+ }
7
+
8
+ .kit-textfield {
9
+ flex: 1 1 auto;
10
+ font-size: 1rem;
11
+ display: grid;
12
+ grid-template-areas:
13
+ 'prepend control append'
14
+ 'a messages b';
15
+ grid-template-columns: max-content minmax(0, 1fr) max-content;
16
+ grid-template-rows: 1fr auto;
17
+ }
18
+
19
+ /* variant */
20
+ .kit-textfield[breakpoint]kit-textfield--variant-filled .kit-field {
21
+ --textfield-border-color: var(--textfield-background);
22
+ background-color: var(--textfield-background);
23
+ border-radius: var(--textfield-radius);
24
+ color: var(--textfield-color);
25
+ }
26
+
27
+ .kit-textfield[breakpoint]kit-textfield--variant-outline .kit-field {
28
+ --textfield-border-color: var(--textfield-color);
29
+ background-color: var(--textfield-background);
30
+ border-radius: var(--textfield-radius);
31
+ color: var(--textfield-color);
32
+ }
33
+
34
+ .kit-textfield[breakpoint]kit-textfield--variant-filled .kit-textfield-outline,
35
+ .kit-textfield[breakpoint]kit-textfield--variant-outline .kit-textfield-outline {
36
+ border-bottom: 1px solid var(--textfield-border-color);
37
+ border-top: 1px solid var(--textfield-border-color);
38
+ border-right: 1px solid var(--textfield-border-color);
39
+ border-left: 1px solid var(--textfield-border-color);
40
+ border-radius: var(--textfield-radius);
41
+ }
42
+
43
+ .kit-textfield[breakpoint]kit-textfield--variant-text .kit-field {
44
+ --textfield-border-color: var(--textfield-color);
45
+ background-color: transparent;
46
+ border-radius: 0;
47
+ color: var(--textfield-color);
48
+ }
49
+
50
+ .kit-textfield[breakpoint]kit-textfield--variant-text .kit-textfield-outline {
51
+ border-bottom: 1px solid var(--textfield-border-color);
52
+ border-top: 0;
53
+ border-right: 0;
54
+ border-left: 0;
55
+ border-radius: 0;
56
+ }
57
+
58
+ .kit-textfield--hide-spin-buttons input[type='number'] {
59
+ -moz-appearance: textfield;
60
+ appearance: textfield;
61
+ }
62
+ .kit-textfield--hide-spin-buttons input[type='number']::-webkit-inner-spin-button,
63
+ .kit-textfield--hide-spin-buttons input[type='number']::-webkit-outer-spin-button {
64
+ display: none;
65
+ -webkit-appearance: none;
66
+ }
67
+
68
+ .kit-textfield--disabled {
69
+ opacity: 0.5;
70
+ pointer-events: none;
71
+ }
72
+
73
+ .kit-textfield--readonly {
74
+ pointer-events: none;
75
+ }
76
+
77
+ .kit-textfield--error .kit-textfield-outline {
78
+ border: 1px solid var(--kit-error);
79
+ }
80
+
81
+ .kit-textfield-outline {
82
+ align-items: stretch;
83
+ contain: layout;
84
+ display: flex;
85
+ height: 100%;
86
+ left: 0;
87
+ pointer-events: none;
88
+ position: absolute;
89
+ right: 0;
90
+ width: 100%;
91
+ }
92
+
93
+ .kit-textfield .kit-textfield-prepend {
94
+ display: flex;
95
+ grid-area: prepend;
96
+ margin-inline-end: 16px;
97
+ align-items: center;
98
+ padding-top: 0;
99
+ }
100
+
101
+ .kit-textfield .kit-textfield-append {
102
+ display: flex;
103
+ grid-area: append;
104
+ margin-inline-start: 16px;
105
+ align-items: center;
106
+ padding-top: 0;
107
+ }
108
+
109
+ /* control */
110
+ .kit-textfield-control {
111
+ display: flex;
112
+ grid-area: control;
113
+ }
114
+
115
+ .kit-textfield-control .kit-textfield-prepend-inner {
116
+ grid-area: prepend-inner;
117
+ display: flex;
118
+ align-items: center;
119
+ padding-top: 0;
120
+ }
121
+ .kit-textfield-control .kit-textfield-clearable {
122
+ cursor: pointer;
123
+ display: flex;
124
+ align-items: center;
125
+ padding-top: 0;
126
+ overflow: hidden;
127
+ margin-inline: 4px;
128
+ grid-area: clear;
129
+ opacity: 0;
130
+ }
131
+
132
+ .kit-textfield-clearable.kit-textfield-clearable--visible {
133
+ opacity: 1;
134
+ }
135
+
136
+ .kit-textfield-control .kit-textfield-append-inner {
137
+ grid-area: append-inner;
138
+ display: flex;
139
+ align-items: center;
140
+ padding-top: 0;
141
+ }
142
+
143
+ /* field prefix suffix */
144
+ .kit-field .kit-field--field .kit-field--field-prefix,
145
+ .kit-field .kit-field--field .kit-field--field-suffix {
146
+ align-items: center;
147
+ cursor: default;
148
+ display: flex;
149
+ transition: inherit;
150
+ white-space: nowrap;
151
+ }
152
+
153
+ /* field */
154
+ .kit-textfield-control .kit-field {
155
+ display: grid;
156
+ grid-template-areas: 'prepend-inner field clear append-inner';
157
+ grid-template-columns: max-content minmax(0, 1fr) max-content max-content;
158
+ font-size: calc(var(--kit-spacing) * var(--textfield-multiplier-font-size));
159
+ max-width: 100%;
160
+ contain: layout;
161
+ flex: 1 0;
162
+ grid-area: control;
163
+ position: relative;
164
+ padding: calc(var(--kit-spacing) * var(--textfield-multiplier-x))
165
+ calc(var(--kit-spacing) * var(--textfield-multiplier-y));
166
+ gap: calc(var(--kit-spacing) * var(--textfield-multiplier-gap));
167
+ }
168
+
169
+ .kit-textfield-control .kit-field .kit-field--field {
170
+ flex: 1 0;
171
+ grid-area: field;
172
+ position: relative;
173
+ align-items: flex-start;
174
+ display: flex;
175
+ }
176
+
177
+ .kit-field .kit-field--field input {
178
+ font: inherit;
179
+ border-radius: 0;
180
+ color: inherit;
181
+ flex: 1;
182
+ min-width: 0;
183
+ align-items: center;
184
+ color: inherit;
185
+ column-gap: 2px;
186
+ display: flex;
187
+ flex-wrap: wrap;
188
+ position: relative;
189
+ width: 100%;
190
+ row-gap: 8px;
191
+ }
192
+
193
+ .kit-field .kit-field--field input:focus,
194
+ .kit-field .kit-field--field input:focus-visible,
195
+ .kit-field .kit-field--field input:active {
196
+ outline: none;
197
+ box-shadow: none;
198
+ }
199
+
200
+ /* message */
201
+ .kit-textfield-message {
202
+ padding-inline: var(--textfield-spacing-y);
203
+ align-items: flex-end;
204
+ display: flex;
205
+ font-size: 0.75rem;
206
+ grid-area: messages;
207
+ min-height: 22px;
208
+ padding-top: var(--textfield-spacing-x);
209
+ overflow: hidden;
210
+ justify-content: space-between;
211
+ opacity: 0;
212
+ }
213
+
214
+ .kit-textfield-message.kit-textfield-message--visible {
215
+ opacity: 1;
216
+ }
217
+
218
+ .kit-message {
219
+ flex: 1 1 auto;
220
+ font-size: 12px;
221
+ min-height: 14px;
222
+ min-width: 1px;
223
+ position: relative;
224
+ display: grid;
225
+ gap: calc(var(--kit-spacing) * var(--textfield-multiplier-gap));
226
+ grid-template-areas: 'message-prepend message message-append ';
227
+ grid-template-columns: max-content minmax(0, 1fr) max-content;
228
+ }
229
+
230
+ .kit-message.kit-message--message-error {
231
+ color: var(--kit-error);
232
+ }
233
+
234
+ .kit-message .kit-message--message {
235
+ line-height: 12px;
236
+ word-break: break-word;
237
+ overflow-wrap: break-word;
238
+ word-wrap: break-word;
239
+ hyphens: auto;
240
+ grid-area: message;
241
+ }
242
+
243
+ .kit-message .kit-message--prepend,
244
+ .kit-message .kit-message--append {
245
+ line-height: 12px;
246
+ }
247
+
248
+ .kit-message .kit-message--prepend {
249
+ grid-area: message-prepend;
250
+ }
251
+ .kit-message .kit-message--append {
252
+ grid-area: message-append;
253
+ }
254
+
255
+ /* size */
256
+ .kit-textfield[breakpoint]kit-textfield--size-xs {
257
+ --textfield-multiplier-x: 2;
258
+ --textfield-multiplier-y: 2;
259
+ --textfield-multiplier-gap: 1;
260
+ --textfield-multiplier-font-size: 6;
261
+ }
262
+
263
+ .kit-textfield[breakpoint]kit-textfield--size-sm {
264
+ --textfield-multiplier-x: 3;
265
+ --textfield-multiplier-y: 4;
266
+ --textfield-multiplier-gap: 2;
267
+ --textfield-multiplier-font-size: 7;
268
+ }
269
+
270
+ .kit-textfield[breakpoint]kit-textfield--size-md {
271
+ --textfield-multiplier-x: 4;
272
+ --textfield-multiplier-y: 6;
273
+ --textfield-multiplier-gap: 2;
274
+ --textfield-multiplier-font-size: 8;
275
+ }
276
+
277
+ .kit-textfield[breakpoint]kit-textfield--size-lg {
278
+ --textfield-multiplier-x: 5;
279
+ --textfield-multiplier-y: 6;
280
+ --textfield-multiplier-gap: 2;
281
+ --textfield-multiplier-font-size: 9;
282
+ }
283
+
284
+ .kit-textfield[breakpoint]kit-textfield--size-xl {
285
+ --textfield-multiplier-x: 6;
286
+ --textfield-multiplier-y: 8;
287
+ --textfield-multiplier-gap: 3;
288
+ --textfield-multiplier-font-size: 10;
289
+ }
290
+
291
+ /*density */
292
+ .kit-textfield[breakpoint]kit-textfield--density-default {
293
+ --textfield-spacing-x: 0;
294
+ --textfield-spacing-y: calc(var(--kit-spacing) * var(--textfield-multiplier-y));
295
+ }
296
+
297
+ .kit-textfield[breakpoint]kit-textfield--density-compact {
298
+ --textfield-spacing-x: calc(0 - 0.5rem);
299
+ --textfield-spacing-y: calc(var(--kit-spacing) * var(--textfield-multiplier-y) - 0.5rem);
300
+ }
301
+
302
+ .kit-textfield[breakpoint]kit-textfield--density-comfortable {
303
+ --textfield-spacing-x: calc(0 + 0.5rem);
304
+ --textfield-spacing-y: calc(var(--kit-spacing) * var(--textfield-multiplier-y) + 0.5rem);
305
+ }
@@ -0,0 +1,193 @@
1
+ <script lang="ts">
2
+ import { getAssets } from '../../internal/index.js';
3
+ import type { TextfieldProps } from './types.js';
4
+
5
+ //external
6
+ import { Icon } from '../index.js';
7
+
8
+ let {
9
+ ref = $bindable(),
10
+ prepend,
11
+ append,
12
+ prependInner,
13
+ appendInner,
14
+ value = $bindable(),
15
+ type = 'text',
16
+ density = 'default',
17
+ size = 'md',
18
+ variant = 'filled',
19
+ placeholder,
20
+ light,
21
+ dark,
22
+ counter,
23
+ min,
24
+ max,
25
+ prefix,
26
+ suffix,
27
+ message,
28
+ messagePrefix,
29
+ messageSuffix,
30
+ clearable,
31
+ persistentClear,
32
+ disabled,
33
+ error,
34
+ errorMessage,
35
+ persistentMessage,
36
+ hideSpinButtons, // only type="number"
37
+ readonly,
38
+ color,
39
+ background,
40
+ rounded,
41
+ ...rest
42
+ }: TextfieldProps = $props();
43
+
44
+ const assets = getAssets();
45
+
46
+ let counterValue: number = $state(0);
47
+ let displayMessage: boolean = $state(false);
48
+ let displayClear: boolean = $state(false);
49
+
50
+ const inputClear = () => {
51
+ value = undefined;
52
+ };
53
+
54
+ const handleFocus = () => {
55
+ if (!error && !persistentMessage) displayMessage = true;
56
+ };
57
+
58
+ const handleBlur = () => {
59
+ if (!error && !persistentMessage) displayMessage = false;
60
+ };
61
+
62
+ $effect(() => {
63
+ if (persistentClear) displayClear = true;
64
+ if (persistentMessage) displayMessage = true;
65
+ else if (error) displayMessage = true;
66
+ else if (!error) displayMessage = false;
67
+ });
68
+
69
+ $effect(() => {
70
+ const valueStr = value?.toString() || '';
71
+
72
+ if (valueStr && typeof max === 'number' && max > 0 && valueStr.length > max) {
73
+ const truncated = valueStr.slice(0, max);
74
+ if (typeof value === 'number') {
75
+ const numValue = Number(truncated);
76
+ value = isNaN(numValue) ? undefined : numValue;
77
+ } else {
78
+ value = truncated;
79
+ }
80
+ }
81
+
82
+ counterValue = valueStr.length;
83
+ });
84
+
85
+ $effect(() => {
86
+ if (!persistentClear) {
87
+ if (value) displayClear = true;
88
+ else displayClear = false;
89
+ }
90
+ });
91
+ </script>
92
+
93
+ <div
94
+ bind:this={ref}
95
+ {...rest}
96
+ class={[
97
+ 'kit-textfield',
98
+ light && 'light',
99
+ dark && 'dark',
100
+ size && assets.className('textfield', 'size', size),
101
+ variant && assets.className('textfield', 'variant', variant),
102
+ density && assets.className('textfield', 'density', density),
103
+ disabled && 'kit-textfield--disabled',
104
+ readonly && 'kit-textfield--readonly',
105
+ error && 'kit-textfield--error',
106
+ type === 'number' && hideSpinButtons && 'kit-textfield--hide-spin-buttons',
107
+ rest.class
108
+ ]}
109
+ style:--base={assets.color(background)}
110
+ style:--on={assets.color(color)}
111
+ style:--shape={assets.shape(rounded)}
112
+ >
113
+ {#if prepend}
114
+ <div class="kit-textfield-prepend">
115
+ {@render prepend?.()}
116
+ </div>
117
+ {/if}
118
+ <div class="kit-textfield-control">
119
+ <div class="kit-field">
120
+ {#if prependInner}
121
+ <div class="kit-textfield-prepend-inner">
122
+ {@render prependInner?.()}
123
+ </div>
124
+ {/if}
125
+ <div class="kit-field--field">
126
+ {#if prefix}
127
+ <span class="kit-field--field-prefix">
128
+ <span class="kit-textfield--field-prefix--text">{prefix}</span>
129
+ </span>
130
+ {/if}
131
+ <input
132
+ {type}
133
+ size="1"
134
+ {placeholder}
135
+ bind:value
136
+ onfocus={handleFocus}
137
+ onblur={handleBlur}
138
+ {...max && { maxlength: max }}
139
+ {...min && { minlength: min }}
140
+ {...disabled && { disabled: true }}
141
+ {...readonly && { readonly: true }}
142
+ />
143
+ {#if suffix}
144
+ <span class="kit-field--field-suffix">
145
+ <span class="kit-textfield--field-suffix--text">{suffix}</span>
146
+ </span>
147
+ {/if}
148
+ </div>
149
+ {#if clearable}
150
+ <div
151
+ class={['kit-textfield-clearable', displayClear && 'kit-textfield-clearable--visible']}
152
+ >
153
+ <Icon icon="mgc_close_circle_fill" onclick={() => inputClear()} />
154
+ </div>
155
+ {/if}
156
+
157
+ {#if appendInner}
158
+ <div class="kit-textfield-append-inner">
159
+ {@render appendInner?.()}
160
+ </div>
161
+ {/if}
162
+
163
+ <div class="kit-textfield-outline"></div>
164
+ </div>
165
+ </div>
166
+ {#if append}
167
+ <div class="kit-textfield-append">
168
+ {@render append?.()}
169
+ </div>
170
+ {/if}
171
+
172
+ <div class={['kit-textfield-message', displayMessage && 'kit-textfield-message--visible']}>
173
+ <div class={['kit-message', error && 'kit-message--message-error']}>
174
+ {#if messagePrefix}
175
+ <div class="kit-message--prepend">{messagePrefix}</div>
176
+ {/if}
177
+ {#if message || error}
178
+ <div class="kit-message--message">
179
+ {error ? errorMessage || message : message}
180
+ </div>
181
+ {/if}
182
+ {#if counter || messageSuffix}
183
+ <div class="kit-message--append">
184
+ {#if counter}
185
+ {counterValue}{max ? `/${max}` : ''}
186
+ {:else if messageSuffix}
187
+ {messageSuffix}
188
+ {/if}
189
+ </div>
190
+ {/if}
191
+ </div>
192
+ </div>
193
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { TextfieldProps } from './types.js';
2
+ declare const Textfield: import("svelte").Component<TextfieldProps, {}, "value" | "ref">;
3
+ type Textfield = ReturnType<typeof Textfield>;
4
+ export default Textfield;
@@ -0,0 +1,37 @@
1
+ import type { Base } from '../../internal/types.js';
2
+ import type { Snippet } from 'svelte';
3
+ export interface TextfieldProps extends Base {
4
+ ref?: HTMLElement | null;
5
+ dark?: boolean;
6
+ light?: boolean;
7
+ value?: string | number;
8
+ type?: 'text' | 'email' | 'password' | 'number';
9
+ placeholder?: string;
10
+ counter?: boolean;
11
+ min?: number;
12
+ max?: number;
13
+ variant?: 'outline' | 'text' | 'filled';
14
+ density?: 'compact' | 'comfortable' | 'default';
15
+ error?: boolean;
16
+ errorMessage?: string;
17
+ disabled?: boolean;
18
+ color?: string;
19
+ background?: string;
20
+ size?: string | {
21
+ [key: string]: string;
22
+ };
23
+ readonly?: boolean;
24
+ hideSpinButtons?: boolean;
25
+ persistentMessage?: boolean;
26
+ persistentClear?: boolean;
27
+ clearable?: boolean;
28
+ message?: string;
29
+ messagePrefix?: string;
30
+ messageSuffix?: string;
31
+ append?: Snippet;
32
+ prepend?: Snippet;
33
+ prependInner?: Snippet;
34
+ appendInner?: Snippet;
35
+ prefix?: string;
36
+ suffix?: string;
37
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lapikit",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"