@t007/input 0.0.22 → 0.0.24

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/README.md CHANGED
@@ -65,6 +65,13 @@ Beautiful floating labels with native error state handling.
65
65
  - **Horizontal Scroll Assist**: Built-in helper for long error messages overflowing the container.
66
66
  - **Tree-Shakeable**: Import only the utilities you need.
67
67
 
68
+ ### Vanilla Perks & Hooks
69
+
70
+ - **`form.onSubmit`**: Optional callback on a form that runs instead of `form.submit()` when provided, allowing custom JS submission flows.
71
+ - **`form.validateOnServer`**: Async hook; if defined the form will await its result before proceeding. Returning `false` prevents submission and shows a global error.
72
+ - **`form.validateOnClient`**: Reference to the internal client-side validation function, allowing you to trigger validation manually or integrate it into custom UI flows.
73
+ - **`form.toggleGlobalError(bool)`**: Programmatic API to display a form-level error state and shake all fields, used internally if `form.validateOnServer` returns false.
74
+
68
75
  ---
69
76
 
70
77
  ## Tech Stack
@@ -122,6 +129,25 @@ myForm.appendChild(emailInput);
122
129
  handleFormValidation(myForm);
123
130
  ```
124
131
 
132
+ ### React
133
+
134
+ ```tsx
135
+ import { Input, WordsInput, useFormManager } from "@t007/input/react";
136
+
137
+ export function SignupForm() {
138
+ const formRef = useRef<HTMLFormElement>(null); // use in a non-form setup or for manual `validate` triggers
139
+ const { handleSubmit, validate, fireInput } = useFormManager((e) => console.log("submitted"), formRef); // first in line to replace browser behaviour effectively
140
+
141
+ return (
142
+ <form noValidate className="t007-input-form" onSubmit={handleSubmit} ref={formRef}>
143
+ <Input type="email" label="Email" required helperText={{ typeMismatch: "Enter a valid email." }} />
144
+ <WordsInput type="textarea" label="Bio" maxCount={120} />
145
+ <button type="submit">Submit</button>
146
+ </form>
147
+ );
148
+ }
149
+ ```
150
+
125
151
  ### CDN / Browser (Global)
126
152
 
127
153
  When loaded via a `<script>` tag, the library automatically scans the DOM for forms with the class `.t007-input-form` and initializes them.
@@ -190,7 +216,7 @@ The core object injected into the global namespace containing utility functions
190
216
 
191
217
  ### File Validation
192
218
 
193
- The library extends native file inputs with custom attributes for strict size enforcement:
219
+ The library extends native file inputs with custom attributes for strict size enforcement, and the same validation logic is available directly through `t007.FM.getFilesHelper(files, opts)`:
194
220
 
195
221
  ```javascript
196
222
  const fileUploader = field({
@@ -204,6 +230,23 @@ const fileUploader = field({
204
230
  });
205
231
  ```
206
232
 
233
+ To use the helper directly, map the same fields into `getFilesHelper` and feed the returned message into your own resolver or `helperText` path:
234
+
235
+ ```javascript
236
+ const { violation, message } = t007.FM.getFilesHelper(input.files, {
237
+ accept: input.accept, // -> typeMismatch
238
+ multiple: input.multiple, // respects file count limits
239
+ maxSize: input.maxSize, // -> rangeOverflow
240
+ minSize: input.minSize, // -> rangeUnderflow
241
+ maxTotalSize: input.maxTotalSize, // -> rangeOverflow
242
+ minTotalSize: input.minTotalSize, // -> rangeUnderflow
243
+ maxLength: input.maxLength, // -> tooLong
244
+ minLength: input.minLength, // -> tooShort
245
+ });
246
+
247
+ if (message) input.setCustomValidity(message);
248
+ ```
249
+
207
250
  ### Password Management
208
251
 
209
252
  Setting an input's custom attribute to `password` or `confirm_password` automatically links their validation states.
@@ -216,13 +259,15 @@ field({ type: 'password', custom: 'password', label: 'Password' });
216
259
  field({ type: 'password', custom: 'confirm_password', label: 'Confirm Password' });
217
260
  ```
218
261
 
262
+ There's other custom features like `onward_date`, `past_date`.
263
+
219
264
  -----
220
265
 
221
266
  ## Customization
222
267
 
223
268
  You can deeply customize the look and feel by overriding the built-in CSS variables or targeting the specific classes.
224
269
 
225
- ### Important Selectors
270
+ ### CSS Selectors & Variables
226
271
 
227
272
  - `.t007-input`: The actual `<input>` element.
228
273
  - `.t007-input-floating-label`: The label text.
@@ -230,6 +275,23 @@ You can deeply customize the look and feel by overriding the built-in CSS variab
230
275
  - `[data-error]`: Attribute added dynamically on validation failure.
231
276
  - `.t007-input-password-strength-meter`: The container for the 4 strength bars.
232
277
 
278
+ #### Override Starter
279
+
280
+ ```css
281
+ .t007-input-field {
282
+ --t007-input-color: var(--app-theme-color);
283
+ /* ...check source code for all variables... */
284
+ }
285
+ ```
286
+
287
+ #### Specificity Note
288
+
289
+ - Start with `:root` for shared input tokens.
290
+ - If a token does not apply, override directly on `.t007-input-field`.
291
+ - For precise control, target element selectors like `.t007-input`, `.t007-input-floating-label`, and `.t007-input-outline`.
292
+ - For strong app themes (e.g. `html[data-theme="dark"]`), use equal/stronger selectors like `html[data-theme="dark"] .t007-input-field`.
293
+ - Check source code for more details.
294
+
233
295
  -----
234
296
 
235
297
  ## Author
package/dist/index.css CHANGED
@@ -5,7 +5,7 @@
5
5
  --t007-input-width: 100%;
6
6
  --t007-input-height: 3rem;
7
7
  --t007-input-font-size: 1rem;
8
- --t007-input-floating-label-scale: 0.75;
8
+ --t007-input-floating-label-scale: 0.85;
9
9
  --t007-input-border-width: 1px;
10
10
  --t007-input-focused-border-width: 2px;
11
11
  --t007-input-border-style: solid;
@@ -58,9 +58,9 @@
58
58
  --t007-input-icon-stroke: unset;
59
59
  --t007-input-padding: calc(var(--t007-input-height) / 4);
60
60
  --t007-input-floating-label-font-size: calc(var(--t007-input-font-size) * var(--t007-input-floating-label-scale));
61
- --t007-input-helper-font-size: calc(var(--t007-input-font-size) * 0.7);
61
+ --t007-input-helper-font-size: calc(var(--t007-input-font-size) * var(--t007-input-floating-label-scale));
62
62
  --t007-input-border-radius: calc(var(--t007-input-height) / 12);
63
- --t007-input-p-meter-font-size: calc(var(--t007-input-font-size) * 0.75);
63
+ --t007-input-p-meter-font-size: calc(var(--t007-input-font-size) * var(--t007-input-floating-label-scale));
64
64
  --t007-input-p-meter-gap: calc(var(--t007-input-font-size) * 0.25);
65
65
  --t007-input-p-meter-height: calc(var(--t007-input-font-size) * 0.25);
66
66
  --t007-input-checkbox-font-size: calc(var(--t007-input-font-size) * 0.9);
@@ -275,7 +275,9 @@
275
275
  .t007-input-floating-label {
276
276
  position: relative;
277
277
  top: calc(var(--t007-input-height) / 2);
278
- display: block;
278
+ display: flex;
279
+ align-items: center;
280
+ gap: calc(var(--t007-input-font-size) / 3);
279
281
  max-width: 100%;
280
282
  transform: translateY(-50%);
281
283
  color: var(--t007-input-current-label-color);
package/dist/index.d.ts CHANGED
@@ -1,52 +1,24 @@
1
1
  import "@t007/utils";
2
+ import { BaseProps, CheckboxInputAddon, DateInputAddon, FileInputAddon, SelectElementAddon } from "../react";
2
3
 
3
- /** Configuration accepted by the field() helper. */
4
- export interface FieldOptions extends Partial<
5
- Omit<HTMLInputElement, "type" | "className" | "children">
6
- > {
7
- /** Wrap the field in its own container. */
8
- isWrapper?: boolean;
4
+ interface BaseOptions extends Omit<BaseProps, "error"> {
9
5
  /** Visible label text. */
10
6
  label?: string;
11
- /** Input type to render. */
12
- type?: string;
13
- /** Placeholder text. */
14
- placeholder?: string;
15
- /** Custom CSS class or class list. */
16
- custom?: string;
17
- /** Minimum value length or count. */
18
- minSize?: number;
19
- /** Maximum value length or count. */
20
- maxSize?: number;
21
- /** Minimum total size allowed across the field value. */
22
- minTotalSize?: number;
23
- /** Maximum total size allowed across the field value. */
24
- maxTotalSize?: number;
25
- /** Options used by select-like fields. */
26
- options?: Array<string | { value: string; option: string }>;
27
- /** Whether the checkbox is partially selected. */
28
- indeterminate?: boolean;
29
- /** Show the password visibility toggler. */
30
- eyeToggler?: boolean;
31
- /** Enable the password strength meter. */
32
- passwordMeter?: boolean;
33
- /** Helper text shown under the field. */
34
- helperText?: false | Record<string, string>;
35
- /** Class applied to the root field element. */
36
- className?: string;
37
- /** Class applied to the inner field control. */
38
- fieldClassName?: string;
39
7
  /** Optional child element rendered inside the field wrapper. */
40
8
  children?: HTMLElement;
41
- /** End icon rendered inside the field control. */
42
- endIcon?: string;
43
- /** Native icon rendered by the browser control. */
44
- nativeIcon?: string;
45
- /** Icon shown when the password is visible. */
46
- passwordVisibleIcon?: string;
47
- /** Icon shown when the password is hidden. */
48
- passwordHiddenIcon?: string;
49
9
  }
10
+ type InputAttrs = Partial<Omit<HTMLInputElement, "type" | "children">>;
11
+ type SelectAttrs = Partial<Omit<HTMLSelectElement, "type" | "children">>;
12
+ type TextareaAttrs = Partial<Omit<HTMLTextAreaElement, "type" | "children">>;
13
+ type PasswordFieldOptions = BaseOptions & InputAttrs & Omit<FileInputAddon, "passwordVisibleIcon" | "passwordHiddenIcon"> & { passwordVisibleIcon?: HTMLElement; passwordHiddenIcon?: HTMLElement };
14
+ type FileFieldOptions = BaseOptions & InputAttrs & FileInputAddon;
15
+ type CheckboxFieldOptions = BaseOptions & InputAttrs & CheckboxInputAddon;
16
+ type DateFieldOptions = BaseOptions & InputAttrs & DateInputAddon;
17
+ type GenericFieldOptions = BaseOptions & InputAttrs & { type?: Exclude<HTMLInputElement["type"], "password" | "file" | "checkbox" | NativeType> };
18
+ type TextareaFieldOptions = BaseOptions & TextareaAttrs & { type: "textarea" };
19
+ type SelectFieldOptions = BaseOptions & SelectAttrs & SelectElementAddon;
20
+ /** Configuration accepted by the field() helper. */
21
+ export type FieldOptions = PasswordFieldOptions | FileFieldOptions | CheckboxFieldOptions | DateFieldOptions | GenericFieldOptions | TextareaFieldOptions | SelectFieldOptions;
50
22
 
51
23
  /** Form-level manager used to build and validate inputs. */
52
24
  export interface FormManager {
@@ -63,10 +35,7 @@ export interface FormManager {
63
35
  * @param opts Validation options.
64
36
  * @returns Violation information and user-facing message.
65
37
  */
66
- getFilesHelper(
67
- files: FileList | File[],
68
- opts: any,
69
- ): { violation: string | null; message: string };
38
+ getFilesHelper(files: FileList | File[], opts: any): { violation: string | null; message: string };
70
39
  /** Format a file size for display.
71
40
  * @param size Size in bytes.
72
41
  * @param decimals Decimal precision.
@@ -135,13 +104,13 @@ declare global {
135
104
  handleFormValidation?: T007Namespace["handleFormValidation"];
136
105
  }
137
106
  interface HTMLFormElement {
138
- /** Client-side submit hook. */
139
- onSubmit?(): void;
140
- /** Check validation on the client. */
107
+ /** Vanilla-only Client-side submit hook. Use instead of `onsubmit` to escape browser behavior. */
108
+ onSubmit?(e: Event): void;
109
+ /** Vanilla-only Check validation on the client. Reference to internals for manual use. */
141
110
  validateOnClient?(): boolean;
142
- /** Check validation on the server. */
111
+ /** Vanilla-only Check validation on the server. Assign custom server-side validation logic. */
143
112
  validateOnServer?(): Promise<boolean>;
144
- /** Toggle the global error state. */
113
+ /** Vanilla-only Toggle the global error state. Reference to internals for manual use. */
145
114
  toggleGlobalError?(bool: boolean): void;
146
115
  }
147
116
  }