@hashrytech/quick-components-kit 0.13.3 → 0.13.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @hashrytech/quick-components-kit
2
2
 
3
+ ## 0.13.5
4
+
5
+ ### Patch Changes
6
+
7
+ - refactor: setting placeholder text size to text-base default
8
+ - refactor: set text size for lg TextInput to text-base
9
+ - patch: adding evaluation of redirect rule to apiclient
10
+
11
+ ## 0.13.4
12
+
13
+ ### Patch Changes
14
+
15
+ - refactor: changing inputClasses prop for TextInput to just class
16
+
3
17
  ## 0.13.3
4
18
 
5
19
  ### Patch Changes
@@ -18,8 +18,7 @@
18
18
  * @prop {string} [name] - The name attribute for form submission.
19
19
  * @prop {string} [value] - The bound value of the input.
20
20
  * @prop {string} [placeholder] - Placeholder text.
21
- * @prop {string} [labelText] - Optional label text.
22
- * @prop {ClassNameValue} [inputClasses] - Additional Tailwind classes to apply to the input. Example: "border-red-500 text-green-600"
21
+ * @prop {string} [labelText] - Optional label text.
23
22
  * @prop {TextInputSize} [size] - Size variant ("sm", "md", "lg") with predefined Tailwind styles.
24
23
  * - "sm": h-[2.05rem] text-sm placeholder:text-sm
25
24
  * - "md": h-[2.375rem] text-sm placeholder:text-sm
@@ -27,6 +26,7 @@
27
26
  * @prop {() => void} [onchange] - Event handler for change events.
28
27
  * @prop {() => void} [onmouseup] - Event handler for mouseup events.
29
28
  * @prop {Snippet} [label] - Custom label snippet.
29
+ * @prop {Snippet} [class] - Css classes for the input element.
30
30
  */
31
31
  export type TextInputProps = {
32
32
  id: string;
@@ -34,8 +34,7 @@
34
34
  value?: string;
35
35
  type?: TextInputType;
36
36
  placeholder?: string;
37
- labelText?: string;
38
- inputClasses?: ClassNameValue;
37
+ labelText?: string;
39
38
  size?: TextInputSize;
40
39
  disabled?: boolean;
41
40
  required?: boolean;
@@ -44,6 +43,7 @@
44
43
  onmouseup?: () => void;
45
44
  label?: Snippet;
46
45
  icon?: Snippet;
46
+ class?: ClassNameValue;
47
47
  };
48
48
 
49
49
 
@@ -52,7 +52,7 @@
52
52
  <script lang="ts">
53
53
  import { twMerge } from 'tailwind-merge';
54
54
 
55
- let { id, type="text", name="", value=$bindable(""), placeholder="", labelText, size="md", inputClasses="", disabled=false, required=false, error, onchange, onmouseup, label, icon}: TextInputProps = $props();
55
+ let { id, type="text", name="", value=$bindable(""), placeholder="", labelText, size="md", disabled=false, required=false, error, onchange, onmouseup, label, icon, ...props}: TextInputProps = $props();
56
56
 
57
57
  /**
58
58
  * Predefined size classes for the TextBox input.
@@ -63,7 +63,7 @@
63
63
  let sizeStyle: Record<TextInputSize, string> = {
64
64
  sm: "h-[2.05rem] text-sm placeholder:text-sm",
65
65
  md: "h-[2.375rem] text-sm placeholder:text-sm",
66
- lg: "h-[2.8rem] text-lg placeholder:text-lg"
66
+ lg: "h-[2.8rem] text-base placeholder:text-base"
67
67
  };
68
68
 
69
69
  </script>
@@ -76,7 +76,7 @@
76
76
  class={twMerge("rounded-primary border-border-primary focus:border-primary-500 focus:ring-primary-500 placeholder:opacity-50 disabled:bg-neutral-300/30 disabled:border-gray-300/30",
77
77
  error ? "bg-red-50 border-red-300 ring-red-300" : "",
78
78
  icon ? "pl-10" : "",
79
- sizeStyle[size], inputClasses)}
79
+ sizeStyle[size], props.class)}
80
80
  />
81
81
  </div>
82
82
  {#if error}
@@ -16,7 +16,6 @@ export type TextInputType = "text" | "password" | "number" | "email" | "tel" | "
16
16
  * @prop {string} [value] - The bound value of the input.
17
17
  * @prop {string} [placeholder] - Placeholder text.
18
18
  * @prop {string} [labelText] - Optional label text.
19
- * @prop {ClassNameValue} [inputClasses] - Additional Tailwind classes to apply to the input. Example: "border-red-500 text-green-600"
20
19
  * @prop {TextInputSize} [size] - Size variant ("sm", "md", "lg") with predefined Tailwind styles.
21
20
  * - "sm": h-[2.05rem] text-sm placeholder:text-sm
22
21
  * - "md": h-[2.375rem] text-sm placeholder:text-sm
@@ -24,6 +23,7 @@ export type TextInputType = "text" | "password" | "number" | "email" | "tel" | "
24
23
  * @prop {() => void} [onchange] - Event handler for change events.
25
24
  * @prop {() => void} [onmouseup] - Event handler for mouseup events.
26
25
  * @prop {Snippet} [label] - Custom label snippet.
26
+ * @prop {Snippet} [class] - Css classes for the input element.
27
27
  */
28
28
  export type TextInputProps = {
29
29
  id: string;
@@ -32,7 +32,6 @@ export type TextInputProps = {
32
32
  type?: TextInputType;
33
33
  placeholder?: string;
34
34
  labelText?: string;
35
- inputClasses?: ClassNameValue;
36
35
  size?: TextInputSize;
37
36
  disabled?: boolean;
38
37
  required?: boolean;
@@ -41,6 +40,7 @@ export type TextInputProps = {
41
40
  onmouseup?: () => void;
42
41
  label?: Snippet;
43
42
  icon?: Snippet;
43
+ class?: ClassNameValue;
44
44
  };
45
45
  declare const TextInput: import("svelte").Component<TextInputProps, {}, "value">;
46
46
  type TextInput = ReturnType<typeof TextInput>;
@@ -9,6 +9,12 @@ import { type ProblemDetail } from "./problem-details.js";
9
9
  * and API routes) to automatically benefit from its enhancements (e.g., cookie forwarding,
10
10
  * built-in request/response interception via SvelteKit's `handleFetch` hook).
11
11
  */
12
+ export interface AutoRedirectRule {
13
+ status: number;
14
+ errorKey: string;
15
+ errorValue?: string;
16
+ redirectTo: string;
17
+ }
12
18
  export type ApiResponse<T> = {
13
19
  ok: boolean;
14
20
  status: number;
@@ -26,6 +32,7 @@ export interface ApiClientConfig {
26
32
  * handled by `src/hooks.server.ts` via `handleFetch`.
27
33
  */
28
34
  getAccessToken?: () => string | undefined;
35
+ autoRedirects?: AutoRedirectRule[];
29
36
  }
30
37
  export interface RequestOptions extends RequestInit {
31
38
  /** If true, the Authorization header will not be added to this request. */
@@ -82,6 +89,7 @@ export declare class ApiClient {
82
89
  private clientAuthToken;
83
90
  private getAccessTokenFromStore;
84
91
  private fetchInstance?;
92
+ private autoRedirects;
85
93
  private requestInterceptors;
86
94
  private responseInterceptors;
87
95
  private errorHandlers;
@@ -155,6 +163,7 @@ export declare class ApiClient {
155
163
  * @template T - Expected type of the response data.
156
164
  */
157
165
  request<T>(endpoint: string, method: string, body: BodyInit | object | null | undefined, options?: RequestOptions): Promise<ApiResponse<T>>;
166
+ private evaluateRedirect;
158
167
  /**
159
168
  * Sends a GET request to the specified API endpoint.
160
169
  *
@@ -1,5 +1,7 @@
1
1
  // src/lib/api/client.ts
2
+ import { redirect } from "@sveltejs/kit";
2
3
  import { getProblemDetail } from "./problem-details.js";
4
+ import { browser } from "$app/environment";
3
5
  /**
4
6
  * Custom error class for API responses.
5
7
  * Provides access to the HTTP status code.
@@ -35,6 +37,7 @@ export class ApiClient {
35
37
  clientAuthToken;
36
38
  getAccessTokenFromStore;
37
39
  fetchInstance;
40
+ autoRedirects = [];
38
41
  requestInterceptors = [];
39
42
  responseInterceptors = [];
40
43
  errorHandlers = [];
@@ -47,6 +50,7 @@ export class ApiClient {
47
50
  this.baseURL = config.baseURL;
48
51
  this.defaultHeaders = config.defaultHeaders || { 'Content-Type': 'application/json' };
49
52
  this.getAccessTokenFromStore = config.getAccessToken;
53
+ this.autoRedirects = config.autoRedirects || [];
50
54
  }
51
55
  /**
52
56
  * Sets the Bearer token for client-side requests.
@@ -247,6 +251,7 @@ export class ApiClient {
247
251
  const message = error instanceof Error ? error.message : 'Unexpected error occurred';
248
252
  const errorObj = isApiError && error.json ? error.json : getProblemDetail({ status, title: "Server fetch error", type: "/exceptions/fetch-error/", detail: message });
249
253
  //const errorObj = status != 503 ? message : getProblemDetail({status, title: "Server fetch error", type: "/exceptions/fetch-error/", detail: "Error fetching data from API", server: message });
254
+ this.evaluateRedirect(errorObj, status);
250
255
  return {
251
256
  ok: false,
252
257
  status,
@@ -254,6 +259,24 @@ export class ApiClient {
254
259
  };
255
260
  }
256
261
  }
262
+ evaluateRedirect(errorObj, status) {
263
+ for (const rule of this.autoRedirects) {
264
+ // Checks if the error matches the redirect rule value can be undefined to match if no value is specified.
265
+ if (status === rule.status && rule.errorKey in errorObj && (rule.errorValue === undefined || errorObj[rule.errorKey] === rule.errorValue)) {
266
+ if (browser) {
267
+ // Client-side redirect
268
+ import('$app/navigation').then(({ goto }) => {
269
+ goto(rule.redirectTo, { replaceState: true });
270
+ });
271
+ }
272
+ else {
273
+ // Server-side redirect
274
+ throw redirect(303, rule.redirectTo);
275
+ }
276
+ break;
277
+ }
278
+ }
279
+ }
257
280
  // --- HTTP Method Shorthands ---
258
281
  /**
259
282
  * Sends a GET request to the specified API endpoint.
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/hashrytech/quick-components-kit.git"
7
7
  },
8
- "version": "0.13.3",
8
+ "version": "0.13.5",
9
9
  "license": "MIT",
10
10
  "author": "Hashry Tech",
11
11
  "files": [