@immich/ui 0.29.0 → 0.30.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.
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">
2
2
  import { getFieldContext } from '../../common/context.svelte.js';
3
+ import Icon from '../Icon/Icon.svelte';
3
4
  import Label from '../Label/Label.svelte';
4
5
  import Text from '../Text/Text.svelte';
5
6
  import type { InputProps } from '../../types.js';
6
7
  import { cleanClass, generateId, isIconLike } from '../../utils.js';
7
- import Icon from '../Icon/Icon.svelte';
8
8
  import { tv } from 'tailwind-variants';
9
9
 
10
10
  let {
@@ -16,6 +16,7 @@
16
16
  value = $bindable<string>(),
17
17
  leadingIcon,
18
18
  trailingIcon,
19
+ trailingText,
19
20
  inputSize,
20
21
  ...restProps
21
22
  }: InputProps = $props();
@@ -24,7 +25,7 @@
24
25
  $derived(getFieldContext());
25
26
 
26
27
  const iconStyles = tv({
27
- base: 'absolute inset-y-0 flex items-center justify-around',
28
+ base: 'flex flex-shrink-0 items-center justify-center',
28
29
  variants: {
29
30
  size: {
30
31
  tiny: 'w-6',
@@ -36,18 +37,14 @@
36
37
  },
37
38
  });
38
39
 
39
- const inputStyles = tv({
40
- base: 'w-full bg-gray-200 outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-400 dark:bg-gray-600 dark:disabled:bg-gray-800 dark:disabled:text-gray-200',
40
+ const containerStyles = tv({
41
+ base: 'flex w-full items-center bg-gray-200 outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-400 dark:bg-gray-600 dark:disabled:bg-gray-800 dark:disabled:text-gray-200',
41
42
  variants: {
42
43
  shape: {
43
44
  rectangle: 'rounded-none',
44
45
  'semi-round': '',
45
46
  round: 'rounded-full',
46
47
  },
47
- padding: {
48
- base: 'px-4 py-3',
49
- round: 'px-5 py-3',
50
- },
51
48
  roundedSize: {
52
49
  tiny: 'rounded-xl',
53
50
  small: 'rounded-xl',
@@ -55,21 +52,16 @@
55
52
  large: 'rounded-2xl',
56
53
  giant: 'rounded-2xl',
57
54
  },
58
- // match with Button `iconSize` variants
59
- paddingLeft: {
60
- tiny: 'ps-6',
61
- small: 'ps-8',
62
- medium: 'ps-10',
63
- large: 'ps-12',
64
- giant: 'ps-14',
65
- },
66
- paddingRight: {
67
- tiny: 'pe-6',
68
- small: 'pe-8',
69
- medium: 'pe-10',
70
- large: 'pe-12',
71
- giant: 'pe-14',
55
+ invalid: {
56
+ true: 'border-danger/80 border',
57
+ false: '',
72
58
  },
59
+ },
60
+ });
61
+
62
+ const inputStyles = tv({
63
+ base: 'flex-1 bg-transparent py-3 outline-none disabled:cursor-not-allowed',
64
+ variants: {
73
65
  textSize: {
74
66
  tiny: 'text-xs',
75
67
  small: 'text-sm',
@@ -77,9 +69,22 @@
77
69
  large: 'text-lg',
78
70
  giant: 'text-xl',
79
71
  },
80
- invalid: {
81
- true: 'border-danger/80 border',
82
- false: '',
72
+ leadingPadding: {
73
+ base: 'pl-4',
74
+ icon: 'pl-0',
75
+ },
76
+ trailingPadding: {
77
+ base: 'pr-4',
78
+ icon: 'pr-0',
79
+ },
80
+ },
81
+ });
82
+
83
+ const trailingTextStyles = tv({
84
+ variants: {
85
+ padding: {
86
+ base: 'px-4',
87
+ icon: 'pl-4',
83
88
  },
84
89
  },
85
90
  });
@@ -99,18 +104,26 @@
99
104
  <Text color="secondary" size="small" id={descriptionId}>{description}</Text>
100
105
  {/if}
101
106
 
102
- <div class="relative w-full">
107
+ <div
108
+ class={cleanClass(
109
+ containerStyles({
110
+ shape,
111
+ roundedSize: shape === 'semi-round' ? size : undefined,
112
+ invalid,
113
+ }),
114
+ className,
115
+ )}
116
+ >
103
117
  {#if leadingIcon}
104
118
  <div tabindex="-1" class={iconStyles({ size })}>
105
- {#if leadingIcon}
106
- {#if isIconLike(leadingIcon)}
107
- <Icon size="60%" icon={leadingIcon} />
108
- {:else}
109
- {@render leadingIcon()}
110
- {/if}
119
+ {#if isIconLike(leadingIcon)}
120
+ <Icon size="60%" icon={leadingIcon} />
121
+ {:else}
122
+ {@render leadingIcon()}
111
123
  {/if}
112
124
  </div>
113
125
  {/if}
126
+
114
127
  <input
115
128
  id={inputId}
116
129
  aria-labelledby={label && labelId}
@@ -122,30 +135,29 @@
122
135
  readonly={readOnly}
123
136
  size={inputSize}
124
137
  aria-readonly={readOnly}
125
- class={cleanClass(
126
- inputStyles({
127
- shape,
128
- textSize: size,
129
- padding: shape === 'round' ? 'round' : 'base',
130
- paddingLeft: leadingIcon ? size : undefined,
131
- paddingRight: trailingIcon ? size : undefined,
132
- roundedSize: shape === 'semi-round' ? size : undefined,
133
- invalid,
134
- }),
135
- className,
136
- )}
138
+ class={inputStyles({
139
+ textSize: size,
140
+ leadingPadding: leadingIcon ? 'icon' : 'base',
141
+ trailingPadding: trailingIcon || trailingText ? 'icon' : 'base',
142
+ })}
137
143
  bind:this={ref}
138
144
  bind:value
139
145
  {...restProps}
140
146
  />
147
+ {#if trailingText}
148
+ <Text
149
+ {size}
150
+ color="muted"
151
+ class={trailingTextStyles({ padding: trailingIcon ? 'icon' : 'base' })}>{trailingText}</Text
152
+ >
153
+ {/if}
154
+
141
155
  {#if trailingIcon}
142
- <div tabindex="-1" class={cleanClass(iconStyles({ size }), 'end-0')}>
143
- {#if trailingIcon}
144
- {#if isIconLike(trailingIcon)}
145
- <Icon size="60%" icon={trailingIcon} />
146
- {:else}
147
- {@render trailingIcon()}
148
- {/if}
156
+ <div tabindex="-1" class={iconStyles({ size })}>
157
+ {#if isIconLike(trailingIcon)}
158
+ <Icon size="60%" icon={trailingIcon} />
159
+ {:else}
160
+ {@render trailingIcon()}
149
161
  {/if}
150
162
  </div>
151
163
  {/if}
package/dist/types.d.ts CHANGED
@@ -117,6 +117,7 @@ export type InputProps = BaseInputProps & {
117
117
  type?: HTMLInputAttributes['type'];
118
118
  leadingIcon?: IconLike | Snippet;
119
119
  trailingIcon?: IconLike | Snippet;
120
+ trailingText?: string;
120
121
  };
121
122
  export type PasswordInputProps = BaseInputProps & {
122
123
  ref?: HTMLInputElement | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immich/ui",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "license": "GNU Affero General Public License version 3",
5
5
  "scripts": {
6
6
  "create": "node scripts/create.js",