@mohasinac/appkit 2.7.34 → 2.7.35

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.
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ export interface DateInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
3
+ label?: React.ReactNode;
4
+ error?: React.ReactNode;
5
+ helperText?: React.ReactNode;
6
+ value?: string;
7
+ onChange?: (value: string) => void;
8
+ }
9
+ export declare const DateInput: React.ForwardRefExoticComponent<DateInputProps & React.RefAttributes<HTMLInputElement>>;
10
+ export interface DateRangeInputProps {
11
+ label?: React.ReactNode;
12
+ startLabel?: string;
13
+ endLabel?: string;
14
+ startValue?: string;
15
+ endValue?: string;
16
+ onStartChange?: (value: string) => void;
17
+ onEndChange?: (value: string) => void;
18
+ error?: React.ReactNode;
19
+ helperText?: React.ReactNode;
20
+ disabled?: boolean;
21
+ required?: boolean;
22
+ startMin?: string;
23
+ startMax?: string;
24
+ endMin?: string;
25
+ endMax?: string;
26
+ }
27
+ export declare function DateRangeInput({ label, startLabel, endLabel, startValue, endValue, onStartChange, onEndChange, error, helperText, disabled, required, startMin, startMax, endMin, endMax, }: DateRangeInputProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import { Label, Text } from "./Typography";
4
+ export const DateInput = React.forwardRef(function DateInput({ label, error, helperText, value, onChange, disabled, required, id, className = "", ...props }, ref) {
5
+ const generatedId = React.useId();
6
+ const inputId = id ?? generatedId;
7
+ return (_jsxs("div", { className: "w-full", children: [label && (_jsx(Label, { htmlFor: inputId, required: required, className: "appkit-form-field__label mb-1.5", children: label })), _jsx("input", { ...props, ref: ref, id: inputId, type: "date", value: value, disabled: disabled, required: required, "aria-invalid": error ? "true" : undefined, onChange: (e) => onChange?.(e.target.value), className: ["appkit-input", error ? "appkit-input--error" : "", className].filter(Boolean).join(" ") }), error ? (_jsx(Text, { size: "sm", variant: "error", role: "alert", className: "mt-1.5", children: error })) : helperText ? (_jsx(Text, { size: "sm", variant: "secondary", className: "mt-1.5", children: helperText })) : null] }));
8
+ });
9
+ export function DateRangeInput({ label, startLabel = "From", endLabel = "To", startValue, endValue, onStartChange, onEndChange, error, helperText, disabled, required, startMin, startMax, endMin, endMax, }) {
10
+ return (_jsxs("div", { className: "w-full", children: [label && (_jsx(Text, { size: "sm", className: "appkit-form-field__label mb-1.5 block font-medium", children: label })), _jsxs("div", { className: "flex items-end gap-2", children: [_jsx(DateInput, { label: startLabel, value: startValue, onChange: onStartChange, disabled: disabled, required: required, min: startMin, max: startMax ?? endValue }), _jsx("span", { className: "mb-2.5 shrink-0 text-sm text-[var(--appkit-color-text-muted)]", children: "\u2013" }), _jsx(DateInput, { label: endLabel, value: endValue, onChange: onEndChange, disabled: disabled, min: endMin ?? startValue, max: endMax })] }), error ? (_jsx(Text, { size: "sm", variant: "error", role: "alert", className: "mt-1.5", children: error })) : helperText ? (_jsx(Text, { size: "sm", variant: "secondary", className: "mt-1.5", children: helperText })) : null] }));
11
+ }
@@ -2,6 +2,7 @@ import { type SelectOption } from "./Select";
2
2
  export interface FormFieldProps {
3
3
  label?: string;
4
4
  name: string;
5
+ card?: boolean;
5
6
  type?: "text" | "email" | "password" | "tel" | "number" | "datetime-local" | "textarea" | "select" | "image" | "media";
6
7
  value?: string;
7
8
  onChange?: (value: string) => void;
@@ -22,5 +23,5 @@ export interface FormFieldProps {
22
23
  accept?: string;
23
24
  maxSizeMB?: number;
24
25
  }
25
- export declare function FormField({ label, name, type, value, onChange, onBlur, error, touched, placeholder, required, disabled, autoComplete, rows, hint, helpText, options, onUpload, captureSource, captureMode, accept, maxSizeMB, }: FormFieldProps): import("react/jsx-runtime").JSX.Element;
26
+ export declare function FormField({ label, name, card, type, value, onChange, onBlur, error, touched, placeholder, required, disabled, autoComplete, rows, hint, helpText, options, onUpload, captureSource, captureMode, accept, maxSizeMB, }: FormFieldProps): import("react/jsx-runtime").JSX.Element;
26
27
  export default FormField;
@@ -4,7 +4,9 @@ import { Select } from "./Select";
4
4
  import { Textarea } from "./Textarea";
5
5
  import { Label, Text, Span } from "./Typography";
6
6
  import { ImageUpload, MediaUploadField } from "../../features/media";
7
- export function FormField({ label, name, type = "text", value = "", onChange, onBlur, error, touched, placeholder, required = false, disabled = false, autoComplete, rows, hint, helpText, options = [], onUpload, captureSource, captureMode, accept, maxSizeMB, }) {
7
+ const CARD_CLASS = "appkit-form-field appkit-form-field--card";
8
+ const BASE_CLASS = "appkit-form-field";
9
+ export function FormField({ label, name, card = false, type = "text", value = "", onChange, onBlur, error, touched, placeholder, required = false, disabled = false, autoComplete, rows, hint, helpText, options = [], onUpload, captureSource, captureMode, accept, maxSizeMB, }) {
8
10
  const showError = error
9
11
  ? touched != null
10
12
  ? touched && !!error
@@ -14,11 +16,11 @@ export function FormField({ label, name, type = "text", value = "", onChange, on
14
16
  const errorId = `${inputId}-error`;
15
17
  const describedBy = showError ? errorId : undefined;
16
18
  if (type === "image" && onUpload) {
17
- return (_jsxs("div", { className: "appkit-form-field", "data-section": "formfield-div-505", children: [_jsx(ImageUpload, { currentImage: value || undefined, onUpload: onUpload, onChange: (url) => onChange?.(url), label: label ? `${label}${required ? " *" : ""}` : undefined, helperText: hint ?? helpText, captureSource: captureSource ?? "file-only", accept: accept, maxSizeMB: maxSizeMB }), showError ? (_jsx(Text, { id: errorId, size: "sm", variant: "error", className: "appkit-form-field__error", role: "alert", children: error })) : null] }));
19
+ return (_jsxs("div", { className: card ? CARD_CLASS : BASE_CLASS, "data-section": "formfield-div-505", children: [_jsx(ImageUpload, { currentImage: value || undefined, onUpload: onUpload, onChange: (url) => onChange?.(url), label: label ? `${label}${required ? " *" : ""}` : undefined, helperText: hint ?? helpText, captureSource: captureSource ?? "file-only", accept: accept, maxSizeMB: maxSizeMB }), showError ? (_jsx(Text, { id: errorId, size: "sm", variant: "error", className: "appkit-form-field__error", role: "alert", children: error })) : null] }));
18
20
  }
19
21
  if (type === "media" && onUpload) {
20
- return (_jsxs("div", { className: "appkit-form-field", "data-section": "formfield-div-506", children: [_jsx(MediaUploadField, { label: `${label || name}${required ? " *" : ""}`, value: value, onChange: (url) => onChange?.(url), onUpload: onUpload, disabled: disabled, helperText: hint ?? helpText, captureSource: captureSource ?? "file-only", captureMode: captureMode ?? "both", accept: accept, maxSizeMB: maxSizeMB }), showError ? (_jsx(Text, { id: errorId, size: "sm", variant: "error", className: "appkit-form-field__error", role: "alert", children: error })) : null] }));
22
+ return (_jsxs("div", { className: card ? CARD_CLASS : BASE_CLASS, "data-section": "formfield-div-506", children: [_jsx(MediaUploadField, { label: `${label || name}${required ? " *" : ""}`, value: value, onChange: (url) => onChange?.(url), onUpload: onUpload, disabled: disabled, helperText: hint ?? helpText, captureSource: captureSource ?? "file-only", captureMode: captureMode ?? "both", accept: accept, maxSizeMB: maxSizeMB }), showError ? (_jsx(Text, { id: errorId, size: "sm", variant: "error", className: "appkit-form-field__error", role: "alert", children: error })) : null] }));
21
23
  }
22
- return (_jsxs("div", { className: "appkit-form-field", "data-section": "formfield-div-507", children: [label ? (_jsxs(Label, { htmlFor: inputId, className: "appkit-form-field__label", children: [label, required ? (_jsx(Span, { className: "appkit-form-field__required", children: "*" })) : null] })) : null, type === "select" ? (_jsx(Select, { id: inputId, name: name, value: value, onChange: (event) => onChange?.(event.target.value), onBlur: onBlur, disabled: disabled, options: options, "aria-required": required || undefined, "aria-invalid": showError || undefined, "aria-describedby": describedBy })) : type === "textarea" ? (_jsx(Textarea, { id: inputId, name: name, value: value, onChange: (event) => onChange?.(event.target.value), onBlur: onBlur, placeholder: placeholder, disabled: disabled, rows: rows, "aria-required": required || undefined, "aria-invalid": showError || undefined, "aria-describedby": describedBy })) : (_jsx(Input, { id: inputId, name: name, type: type, value: value, onChange: (event) => onChange?.(event.target.value), onBlur: onBlur, placeholder: placeholder, disabled: disabled, autoComplete: autoComplete, "aria-required": required || undefined, "aria-invalid": showError || undefined, "aria-describedby": describedBy })), !showError && (hint || helpText) ? (_jsx(Text, { size: "sm", variant: "secondary", className: "appkit-form-field__hint", children: hint ?? helpText })) : null, showError ? (_jsx(Text, { id: errorId, size: "sm", variant: "error", className: "appkit-form-field__error", role: "alert", children: error })) : null] }));
24
+ return (_jsxs("div", { className: card ? CARD_CLASS : BASE_CLASS, "data-section": "formfield-div-507", children: [label ? (_jsxs(Label, { htmlFor: inputId, className: "appkit-form-field__label", children: [label, required ? (_jsx(Span, { className: "appkit-form-field__required", children: "*" })) : null] })) : null, type === "select" ? (_jsx(Select, { id: inputId, name: name, value: value, onChange: (event) => onChange?.(event.target.value), onBlur: onBlur, disabled: disabled, options: options, "aria-required": required || undefined, "aria-invalid": showError || undefined, "aria-describedby": describedBy })) : type === "textarea" ? (_jsx(Textarea, { id: inputId, name: name, value: value, onChange: (event) => onChange?.(event.target.value), onBlur: onBlur, placeholder: placeholder, disabled: disabled, rows: rows, "aria-required": required || undefined, "aria-invalid": showError || undefined, "aria-describedby": describedBy })) : (_jsx(Input, { id: inputId, name: name, type: type, value: value, onChange: (event) => onChange?.(event.target.value), onBlur: onBlur, placeholder: placeholder, disabled: disabled, autoComplete: autoComplete, "aria-required": required || undefined, "aria-invalid": showError || undefined, "aria-describedby": describedBy })), !showError && (hint || helpText) ? (_jsx(Text, { size: "sm", variant: "secondary", className: "appkit-form-field__hint", children: hint ?? helpText })) : null, showError ? (_jsx(Text, { id: errorId, size: "sm", variant: "error", className: "appkit-form-field__error", role: "alert", children: error })) : null] }));
23
25
  }
24
26
  export default FormField;
@@ -28,3 +28,16 @@
28
28
  .appkit-form-field__error {
29
29
  margin-top: 0.375rem;
30
30
  }
31
+
32
+ /* Card variant — adds a contained panel treatment around label + field */
33
+ .appkit-form-field--card {
34
+ background: var(--appkit-color-zinc-50, #fafafa);
35
+ border: 1px solid var(--appkit-color-zinc-200, #e4e4e7);
36
+ border-radius: 0.5rem;
37
+ padding: 1rem;
38
+ }
39
+
40
+ .dark .appkit-form-field--card {
41
+ background: rgba(30, 41, 59, 0.4);
42
+ border-color: rgba(71, 85, 105, 0.6);
43
+ }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useRef, useState, useEffect, useCallback, cloneElement, } from "react";
3
+ import { useRef, useState, useEffect, useCallback, } from "react";
4
4
  import { ChevronLeft, ChevronRight } from "lucide-react";
5
5
  const BREAKPOINTS = [
6
6
  ["2xl", 1536],
@@ -23,6 +23,7 @@ function resolvePerView(perView, containerWidth) {
23
23
  }
24
24
  export function HorizontalScroller({ children, className = "", gap = 16, snapToItems, showArrows, arrowSize = "md", showScrollbar, showFadeEdges, scrollContainerRef: externalRef, onScroll, items, renderItem, keyExtractor, perView, rows = 1, autoScroll, autoScrollInterval = 3500, minItemWidth, pauseOnHover = false, itemClassName = "", loop = false, }) {
25
25
  const [itemWidth, setItemWidth] = useState(undefined);
26
+ const [colCount, setColCount] = useState(typeof perView === "number" ? perView : 3);
26
27
  const [isPaused, setIsPaused] = useState(false);
27
28
  const [atStart, setAtStart] = useState(true);
28
29
  const [atEnd, setAtEnd] = useState(true);
@@ -144,6 +145,7 @@ export function HorizontalScroller({ children, className = "", gap = 16, snapToI
144
145
  const w = entry.contentRect.width;
145
146
  const count = resolvePerView(perView, w);
146
147
  if (count > 0) {
148
+ setColCount(count);
147
149
  setItemWidth((w - (count - 1) * gap) / count);
148
150
  }
149
151
  updateExtents();
@@ -156,35 +158,28 @@ export function HorizontalScroller({ children, className = "", gap = 16, snapToI
156
158
  updateExtents();
157
159
  }, [updateExtents, itemWidth, itemCount]);
158
160
  const content = itemsMode ? (rows > 1 ? (
159
- // Grid mode: group items into slides with rows x cols
160
- normalizedItems.reduce((slides, item, i) => {
161
- const cardsPerSlide = 6;
162
- const slideIndex = Math.floor(i / cardsPerSlide);
163
- const itemInSlide = i % cardsPerSlide;
164
- const rowIndex = Math.floor(itemInSlide / 3);
165
- const colIndex = itemInSlide % 3;
166
- if (!slides[slideIndex]) {
167
- slides[slideIndex] = (_jsx("div", { className: "appkit-hscroller__slide grid grid-cols-1 sm:grid-cols-3 gap-4 place-items-center sm:place-items-start", style: { gap: `${gap}px`, width: "100%", flexShrink: 0 }, children: Array.from({ length: 6 }, (_, idx) => (_jsx("div", { className: "appkit-hscroller__item-placeholder w-full sm:w-auto" }, `placeholder-${idx}`))) }, `slide-${slideIndex}`));
168
- }
169
- const slideElement = slides[slideIndex];
170
- const gridIndex = rowIndex * 3 + colIndex;
171
- const childrenArr = slideElement.props.children ?? [];
172
- if (childrenArr[gridIndex]) {
173
- const newChildren = [...childrenArr];
174
- newChildren[gridIndex] = (_jsx("div", { className: [
175
- "appkit-hscroller__item",
176
- snapToItems ? "appkit-hscroller__item--snap" : "",
177
- itemClassName,
178
- "w-full sm:w-auto",
179
- ]
180
- .filter(Boolean)
181
- .join(" "), style: minItemWidth ? { minWidth: minItemWidth } : undefined, children: renderItem(item, i) }, keyExtractor ? keyExtractor(item, i) : i));
182
- slides[slideIndex] = cloneElement(slideElement, {
183
- children: newChildren,
184
- });
185
- }
186
- return slides;
187
- }, [])) : loop && itemCount > 0 ? (
161
+ // Grid mode: group items into slides of (rows × colCount) cards
162
+ (() => {
163
+ const cols = colCount > 0 ? colCount : 3;
164
+ const cardsPerSlide = rows * cols;
165
+ const slideCount = Math.ceil(normalizedItems.length / cardsPerSlide);
166
+ return Array.from({ length: slideCount }, (_, slideIndex) => {
167
+ const slideItems = normalizedItems.slice(slideIndex * cardsPerSlide, (slideIndex + 1) * cardsPerSlide);
168
+ return (_jsx("div", { className: "appkit-hscroller__slide", style: {
169
+ display: "grid",
170
+ gridTemplateColumns: `repeat(${cols}, 1fr)`,
171
+ gap: `${gap}px`,
172
+ width: "100%",
173
+ flexShrink: 0,
174
+ }, children: slideItems.map((item, idx) => (_jsx("div", { className: [
175
+ "appkit-hscroller__item",
176
+ snapToItems ? "appkit-hscroller__item--snap" : "",
177
+ itemClassName,
178
+ ]
179
+ .filter(Boolean)
180
+ .join(" "), style: minItemWidth ? { minWidth: minItemWidth } : undefined, children: renderItem(item, slideIndex * cardsPerSlide + idx) }, keyExtractor ? keyExtractor(item, slideIndex * cardsPerSlide + idx) : slideIndex * cardsPerSlide + idx))) }, `slide-${slideIndex}`));
181
+ });
182
+ })()) : loop && itemCount > 0 ? (
188
183
  // Circular loop: fixed (itemCount + 2×loopCloneCount) DOM slots.
189
184
  // Each slot maps to a real item via modulo — no array cloning, no list growth.
190
185
  // Left slots [0 .. loopCloneCount-1] → tail of real list (left buffer)
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ export interface OtpInputProps {
3
+ length?: number;
4
+ value: string;
5
+ onChange: (value: string) => void;
6
+ label?: React.ReactNode;
7
+ error?: React.ReactNode;
8
+ helperText?: React.ReactNode;
9
+ disabled?: boolean;
10
+ autoFocus?: boolean;
11
+ inputMode?: "numeric" | "text";
12
+ id?: string;
13
+ }
14
+ export declare function OtpInput({ length, value, onChange, label, error, helperText, disabled, autoFocus, inputMode, id, }: OtpInputProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useRef, useId } from "react";
4
+ import { Label, Text } from "./Typography";
5
+ export function OtpInput({ length = 6, value, onChange, label, error, helperText, disabled = false, autoFocus = false, inputMode = "numeric", id, }) {
6
+ const generatedId = useId();
7
+ const inputId = id ?? generatedId;
8
+ const inputsRef = useRef([]);
9
+ const digits = value.split("").concat(Array(length).fill("")).slice(0, length);
10
+ function focusAt(index) {
11
+ inputsRef.current[index]?.focus();
12
+ }
13
+ function handleChange(index, char) {
14
+ const sanitized = inputMode === "numeric" ? char.replace(/\D/g, "") : char;
15
+ const next = digits.slice();
16
+ next[index] = sanitized.slice(-1);
17
+ onChange(next.join(""));
18
+ if (sanitized && index < length - 1)
19
+ focusAt(index + 1);
20
+ }
21
+ function handleKeyDown(index, e) {
22
+ if (e.key === "ArrowLeft" && index > 0) {
23
+ focusAt(index - 1);
24
+ return;
25
+ }
26
+ if (e.key === "ArrowRight" && index < length - 1) {
27
+ focusAt(index + 1);
28
+ return;
29
+ }
30
+ if (e.key !== "Backspace")
31
+ return;
32
+ if (digits[index]) {
33
+ const next = digits.slice();
34
+ next[index] = "";
35
+ onChange(next.join(""));
36
+ }
37
+ else if (index > 0) {
38
+ focusAt(index - 1);
39
+ }
40
+ }
41
+ function handlePaste(e) {
42
+ e.preventDefault();
43
+ const pasted = e.clipboardData.getData("text");
44
+ const sanitized = inputMode === "numeric" ? pasted.replace(/\D/g, "") : pasted;
45
+ const next = sanitized.slice(0, length).split("").concat(Array(length).fill("")).slice(0, length);
46
+ onChange(next.join(""));
47
+ const lastFilled = Math.min(sanitized.length, length - 1);
48
+ focusAt(lastFilled);
49
+ }
50
+ return (_jsxs("div", { className: "w-full", children: [label && (_jsx(Label, { htmlFor: `${inputId}-0`, className: "appkit-form-field__label mb-2", children: label })), _jsx("div", { className: "flex gap-2", role: "group", "aria-labelledby": label ? `${inputId}-label` : undefined, children: digits.map((digit, i) => (_jsx("input", { ref: (el) => { inputsRef.current[i] = el; }, id: i === 0 ? `${inputId}-0` : undefined, type: "text", inputMode: inputMode, maxLength: 1, value: digit, disabled: disabled, autoFocus: autoFocus && i === 0, autoComplete: "one-time-code", "aria-label": `Digit ${i + 1} of ${length}`, className: [
51
+ "appkit-input",
52
+ "appkit-otp-input",
53
+ error ? "appkit-input--error" : "",
54
+ ].filter(Boolean).join(" "), onChange: (e) => handleChange(i, e.target.value), onKeyDown: (e) => handleKeyDown(i, e), onPaste: handlePaste, onFocus: (e) => e.target.select() }, i))) }), error ? (_jsx(Text, { size: "sm", variant: "error", role: "alert", className: "mt-1.5", children: error })) : helperText ? (_jsx(Text, { size: "sm", variant: "secondary", className: "mt-1.5", children: helperText })) : null] }));
55
+ }
@@ -0,0 +1,13 @@
1
+ .appkit-otp-input {
2
+ width: 2.75rem;
3
+ height: 2.75rem;
4
+ flex-shrink: 0;
5
+ padding: 0;
6
+ text-align: center;
7
+ font-size: 1.25rem;
8
+ font-weight: 600;
9
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
10
+ letter-spacing: 0;
11
+ border-radius: 0.5rem;
12
+ caret-color: transparent;
13
+ }
@@ -23,36 +23,53 @@
23
23
  color: var(--appkit-color-text);
24
24
  padding: 0.5rem 0.75rem;
25
25
  font-size: 0.875rem;
26
- transition: border-color 0.2s ease, box-shadow 0.2s ease;
26
+ transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
27
27
  }
28
28
 
29
29
  .dark .appkit-select__trigger {
30
30
  border-color: var(--appkit-color-border);
31
- background: rgba(30, 41, 59, 0.6);
31
+ background: rgba(30, 41, 59, 0.7);
32
32
  color: var(--appkit-color-text);
33
33
  }
34
34
 
35
+ .appkit-select__trigger--enabled:hover:not(:focus-visible) {
36
+ border-color: var(--appkit-color-zinc-400);
37
+ }
38
+
39
+ .dark .appkit-select__trigger--enabled:hover:not(:focus-visible) {
40
+ border-color: var(--appkit-color-slate-500);
41
+ }
42
+
35
43
  .appkit-select__trigger--default:focus-visible {
44
+ outline: none;
36
45
  border-color: var(--appkit-color-secondary);
37
- box-shadow: 0 0 0 2px rgba(101, 196, 8, 0.2);
46
+ box-shadow: 0 0 0 3px rgba(101, 196, 8, 0.25), inset 0 0 0 1px rgba(101, 196, 8, 0.15);
38
47
  }
39
48
 
40
49
  .dark .appkit-select__trigger--default:focus-visible {
41
50
  border-color: var(--appkit-color-primary);
42
- box-shadow: 0 0 0 2px rgba(233, 30, 140, 0.2);
51
+ box-shadow: 0 0 0 3px rgba(233, 30, 140, 0.25), inset 0 0 0 1px rgba(233, 30, 140, 0.15);
43
52
  }
44
53
 
45
54
  .appkit-select__trigger--error {
46
55
  border-color: var(--appkit-color-error);
56
+ background: rgba(254, 202, 202, 0.06);
47
57
  }
48
58
 
49
59
  .appkit-select__trigger--error:focus-visible {
50
- box-shadow: 0 0 0 2px rgba(248, 113, 113, 0.2);
60
+ outline: none;
61
+ border-color: var(--appkit-color-error);
62
+ box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.25), inset 0 0 0 1px rgba(248, 113, 113, 0.15);
51
63
  }
52
64
 
53
65
  .appkit-select__trigger--disabled {
54
- opacity: 0.5;
66
+ opacity: 0.55;
55
67
  cursor: not-allowed;
68
+ background: var(--appkit-color-bg);
69
+ }
70
+
71
+ .dark .appkit-select__trigger--disabled {
72
+ background: rgba(30, 41, 59, 0.4);
56
73
  }
57
74
 
58
75
  .appkit-select__trigger--enabled {
@@ -9,22 +9,49 @@
9
9
  line-height: var(--appkit-leading-normal);
10
10
  min-height: 5rem;
11
11
  resize: vertical;
12
- transition: border-color 0.2s ease, box-shadow 0.2s ease;
12
+ transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
13
+ }
14
+
15
+ .appkit-textarea::placeholder {
16
+ color: var(--appkit-color-text-faint);
17
+ }
18
+
19
+ .appkit-textarea:hover:not(:disabled):not(:focus-visible) {
20
+ border-color: var(--appkit-color-zinc-400);
13
21
  }
14
22
 
15
23
  .appkit-textarea:focus-visible {
16
24
  outline: none;
17
25
  border-color: var(--appkit-color-secondary);
18
- box-shadow: 0 0 0 2px rgba(101, 196, 8, 0.2);
26
+ box-shadow: 0 0 0 3px rgba(101, 196, 8, 0.25), inset 0 0 0 1px rgba(101, 196, 8, 0.15);
27
+ }
28
+
29
+ .appkit-textarea:disabled {
30
+ opacity: 0.55;
31
+ cursor: not-allowed;
32
+ background: var(--appkit-color-bg);
33
+ resize: none;
19
34
  }
20
35
 
21
36
  .dark .appkit-textarea {
22
37
  border-color: var(--appkit-color-border);
23
- background: rgba(30, 41, 59, 0.6);
38
+ background: rgba(30, 41, 59, 0.7);
24
39
  color: var(--appkit-color-text);
25
40
  }
26
41
 
42
+ .dark .appkit-textarea::placeholder {
43
+ color: var(--appkit-color-text-muted);
44
+ }
45
+
46
+ .dark .appkit-textarea:hover:not(:disabled):not(:focus-visible) {
47
+ border-color: var(--appkit-color-slate-500);
48
+ }
49
+
27
50
  .dark .appkit-textarea:focus-visible {
28
51
  border-color: var(--appkit-color-primary);
29
- box-shadow: 0 0 0 2px rgba(233, 30, 140, 0.2);
52
+ box-shadow: 0 0 0 3px rgba(233, 30, 140, 0.25), inset 0 0 0 1px rgba(233, 30, 140, 0.15);
53
+ }
54
+
55
+ .dark .appkit-textarea:disabled {
56
+ background: rgba(30, 41, 59, 0.4);
30
57
  }
@@ -1,6 +1,7 @@
1
1
  @import "./Typography.style.css";
2
2
  @import "./Button.style.css";
3
3
  @import "./Input.style.css";
4
+ @import "./OtpInput.style.css";
4
5
  @import "./Textarea.style.css";
5
6
  @import "./Select.style.css";
6
7
  @import "./Accordion.style.css";
@@ -55,6 +55,10 @@ export type { SelectProps, SelectOption } from "./components/Select";
55
55
  export { Select } from "./components/Select";
56
56
  export type { InputProps } from "./components/Input";
57
57
  export { Input } from "./components/Input";
58
+ export type { OtpInputProps } from "./components/OtpInput";
59
+ export { OtpInput } from "./components/OtpInput";
60
+ export type { DateInputProps, DateRangeInputProps } from "./components/DateInput";
61
+ export { DateInput, DateRangeInput } from "./components/DateInput";
58
62
  export type { TextareaProps } from "./components/Textarea";
59
63
  export { Textarea } from "./components/Textarea";
60
64
  export type { SliderProps } from "./components/Slider";
package/dist/ui/index.js CHANGED
@@ -31,6 +31,8 @@ export { BackgroundRenderer } from "./components/BackgroundRenderer";
31
31
  export { ResponsiveView } from "./components/ResponsiveView";
32
32
  export { Select } from "./components/Select";
33
33
  export { Input } from "./components/Input";
34
+ export { OtpInput } from "./components/OtpInput";
35
+ export { DateInput, DateRangeInput } from "./components/DateInput";
34
36
  export { Textarea } from "./components/Textarea";
35
37
  export { Slider } from "./components/Slider";
36
38
  export { Checkbox } from "./components/Checkbox";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "2.7.34",
3
+ "version": "2.7.35",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"