@zayne-labs/ui-react 0.10.9 → 0.10.11
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/dist/esm/{cn-s-D7vHW1.js → cn-DdD3uYxA.js} +1 -1
- package/dist/esm/{cn-s-D7vHW1.js.map → cn-DdD3uYxA.js.map} +1 -1
- package/dist/esm/common/await/index.d.ts +46 -4
- package/dist/esm/common/await/index.js +86 -4
- package/dist/esm/common/await/index.js.map +1 -0
- package/dist/esm/common/error-boundary/index.d.ts +1 -1
- package/dist/esm/common/for/index.d.ts +23 -2
- package/dist/esm/common/for/index.js +1 -1
- package/dist/esm/common/presence/index.js +1 -1
- package/dist/esm/common/show/index.d.ts +32 -2
- package/dist/esm/common/slot/index.d.ts +16 -2
- package/dist/esm/common/suspense-with-boundary/index.d.ts +2 -2
- package/dist/esm/common/suspense-with-boundary/index.js +20 -3
- package/dist/esm/common/suspense-with-boundary/index.js.map +1 -0
- package/dist/esm/common/switch/index.d.ts +28 -2
- package/dist/esm/common/switch/index.js +37 -2
- package/dist/esm/common/switch/index.js.map +1 -0
- package/dist/esm/common/teleport/index.d.ts +14 -2
- package/dist/esm/common/teleport/index.js +31 -2
- package/dist/esm/common/teleport/index.js.map +1 -0
- package/dist/esm/{for-DK5rEY_m.js → for-BYsFEk3R.js} +1 -1
- package/dist/esm/{for-DK5rEY_m.js.map → for-BYsFEk3R.js.map} +1 -1
- package/dist/esm/{index-C0L6V4Zq.d.ts → index-B0pltiMx.d.ts} +3 -3
- package/dist/esm/{index-lw5txqar.d.ts → index-DGomCOFj.d.ts} +4 -4
- package/dist/esm/{presence-CL5_GHQH.js → presence-CAQElNtY.js} +1 -1
- package/dist/esm/{presence-CL5_GHQH.js.map → presence-CAQElNtY.js.map} +1 -1
- package/dist/esm/ui/card/index.d.ts +20 -2
- package/dist/esm/ui/card/index.js +94 -4
- package/dist/esm/ui/card/index.js.map +1 -0
- package/dist/esm/ui/carousel/index.d.ts +95 -2
- package/dist/esm/ui/carousel/index.js +285 -13
- package/dist/esm/ui/carousel/index.js.map +1 -0
- package/dist/esm/ui/drag-scroll/index.d.ts +23 -2
- package/dist/esm/ui/drag-scroll/index.js +114 -3
- package/dist/esm/ui/drag-scroll/index.js.map +1 -0
- package/dist/esm/ui/drop-zone/index.d.ts +346 -2
- package/dist/esm/ui/drop-zone/index.js +1026 -14
- package/dist/esm/ui/drop-zone/index.js.map +1 -0
- package/dist/esm/ui/form/index.d.ts +227 -2
- package/dist/esm/ui/form/index.js +573 -5
- package/dist/esm/ui/form/index.js.map +1 -0
- package/package.json +6 -8
- package/dist/esm/await-DDgVzpvI.js +0 -87
- package/dist/esm/await-DDgVzpvI.js.map +0 -1
- package/dist/esm/card-DDLJVCwL.js +0 -95
- package/dist/esm/card-DDLJVCwL.js.map +0 -1
- package/dist/esm/carousel-B051PAAX.js +0 -285
- package/dist/esm/carousel-B051PAAX.js.map +0 -1
- package/dist/esm/common/index.d.ts +0 -9
- package/dist/esm/common/index.js +0 -11
- package/dist/esm/common-PS3X58Pj.js +0 -0
- package/dist/esm/drag-scroll-Bb1SG4On.js +0 -115
- package/dist/esm/drag-scroll-Bb1SG4On.js.map +0 -1
- package/dist/esm/drop-zone-FkkbzZ3j.js +0 -1019
- package/dist/esm/drop-zone-FkkbzZ3j.js.map +0 -1
- package/dist/esm/form-DyGy9LnA.js +0 -574
- package/dist/esm/form-DyGy9LnA.js.map +0 -1
- package/dist/esm/index-BJUTFSec.d.ts +0 -227
- package/dist/esm/index-BeCCgTjL.d.ts +0 -16
- package/dist/esm/index-BsGxDKlt.d.ts +0 -32
- package/dist/esm/index-C1GPFYKG.d.ts +0 -23
- package/dist/esm/index-CZjeBSoQ.d.ts +0 -14
- package/dist/esm/index-CffEFE66.d.ts +0 -28
- package/dist/esm/index-DFHOx2Pf.d.ts +0 -23
- package/dist/esm/index-DXwAMkn0.d.ts +0 -46
- package/dist/esm/index-RpfwCCWX.d.ts +0 -345
- package/dist/esm/index-bD-GMufy.d.ts +0 -20
- package/dist/esm/index-ipYGGqwN.d.ts +0 -95
- package/dist/esm/suspense-with-boundary-D-1NYDV4.js +0 -21
- package/dist/esm/suspense-with-boundary-D-1NYDV4.js.map +0 -1
- package/dist/esm/switch-Ch22z21e.js +0 -38
- package/dist/esm/switch-Ch22z21e.js.map +0 -1
- package/dist/esm/teleport-C8TzRm4M.js +0 -32
- package/dist/esm/teleport-C8TzRm4M.js.map +0 -1
- package/dist/esm/ui/index.d.ts +0 -6
- package/dist/esm/ui/index.js +0 -18
|
@@ -1,9 +1,577 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
import "../../
|
|
5
|
-
import "../../
|
|
6
|
-
import "../../
|
|
7
|
-
import {
|
|
4
|
+
import { __export } from "../../chunk-CTAAG5j7.js";
|
|
5
|
+
import { SlotRoot } from "../../slot-WVWfOlr3.js";
|
|
6
|
+
import { ForWithWrapper } from "../../for-BYsFEk3R.js";
|
|
7
|
+
import { cnMerge } from "../../cn-DdD3uYxA.js";
|
|
8
|
+
import { composeRefs, composeTwoEventHandlers, getMultipleSlots } from "@zayne-labs/toolkit-react/utils";
|
|
9
|
+
import { defineEnum, isObject } from "@zayne-labs/toolkit-type-helpers";
|
|
10
|
+
import { Fragment, createElement, useEffect, useId, useMemo, useRef } from "react";
|
|
11
|
+
import { ContextError, createCustomContext, useCallbackRef, useToggle } from "@zayne-labs/toolkit-react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { dataAttr, on, toArray } from "@zayne-labs/toolkit-core";
|
|
14
|
+
import { Controller, FormProvider, useFormContext, useFormContext as useFormRootContext, useFormState, useWatch } from "react-hook-form";
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
//#region src/components/ui/form/icons.tsx
|
|
17
|
+
const EyeIconClosed = (props) => /* @__PURE__ */ jsx("svg", {
|
|
18
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
19
|
+
width: "1em",
|
|
20
|
+
height: "1em",
|
|
21
|
+
viewBox: "0 0 24 24",
|
|
22
|
+
...props,
|
|
23
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
24
|
+
fill: "currentColor",
|
|
25
|
+
d: "M15.175 8.325q.725.725 1.063 1.65t.237 1.9q0 .375-.275.638t-.65.262t-.638-.262t-.262-.638q.125-.65-.075-1.25T13.95 9.6t-1.025-.65t-1.275-.1q-.375 0-.638-.275t-.262-.65t.263-.637t.637-.263q.95-.1 1.875.238t1.65 1.062M12 6q-.475 0-.925.037t-.9.138q-.425.075-.763-.125t-.462-.6t.088-.775t.612-.45q.575-.125 1.163-.175T12 4q3.425 0 6.263 1.8t4.337 4.85q.1.2.15.413t.05.437t-.038.438t-.137.412q-.45 1-1.112 1.875t-1.463 1.6q-.3.275-.7.225t-.65-.4t-.212-.763t.337-.687q.6-.575 1.1-1.25t.875-1.45q-1.25-2.525-3.613-4.012T12 6m0 13q-3.35 0-6.125-1.812T1.5 12.425q-.125-.2-.187-.437T1.25 11.5t.05-.475t.175-.45q.5-1 1.163-1.912T4.15 7L2.075 4.9q-.275-.3-.262-.712T2.1 3.5t.7-.275t.7.275l17 17q.275.275.288.688t-.288.712q-.275.275-.7.275t-.7-.275l-3.5-3.45q-.875.275-1.775.413T12 19M5.55 8.4q-.725.65-1.325 1.425T3.2 11.5q1.25 2.525 3.613 4.013T12 17q.5 0 .975-.062t.975-.138l-.9-.95q-.275.075-.525.113T12 16q-1.875 0-3.188-1.312T7.5 11.5q0-.275.038-.525t.112-.525zm4.2 4.2"
|
|
26
|
+
})
|
|
27
|
+
});
|
|
28
|
+
const EyeIconOpen = (props) => /* @__PURE__ */ jsx("svg", {
|
|
29
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
30
|
+
width: "1em",
|
|
31
|
+
height: "1em",
|
|
32
|
+
viewBox: "0 0 24 24",
|
|
33
|
+
...props,
|
|
34
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
35
|
+
fill: "currentColor",
|
|
36
|
+
d: "M12 16q1.875 0 3.188-1.312T16.5 11.5t-1.312-3.187T12 7T8.813 8.313T7.5 11.5t1.313 3.188T12 16m0-1.8q-1.125 0-1.912-.788T9.3 11.5t.788-1.912T12 8.8t1.913.788t.787 1.912t-.787 1.913T12 14.2m0 4.8q-3.35 0-6.113-1.8t-4.362-4.75q-.125-.225-.187-.462t-.063-.488t.063-.488t.187-.462q1.6-2.95 4.363-4.75T12 4t6.113 1.8t4.362 4.75q.125.225.188.463t.062.487t-.062.488t-.188.462q-1.6 2.95-4.362 4.75T12 19m0-2q2.825 0 5.188-1.487T20.8 11.5q-1.25-2.525-3.613-4.012T12 6T6.813 7.488T3.2 11.5q1.25 2.525 3.613 4.013T12 17"
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/components/ui/form/utils.ts
|
|
42
|
+
const getFieldErrorMessage = (options) => {
|
|
43
|
+
const { errors, fieldName, type } = options;
|
|
44
|
+
if (fieldName === void 0 || !errors || Object.keys(errors).length === 0) return;
|
|
45
|
+
if (type === "root") return errors.root?.[fieldName]?.message;
|
|
46
|
+
const pathParts = fieldName.includes(".") ? fieldName.split(".") : null;
|
|
47
|
+
if (!pathParts) return errors[fieldName]?.message;
|
|
48
|
+
let extractedError = errors;
|
|
49
|
+
for (const part of pathParts) {
|
|
50
|
+
const currentError = extractedError[part];
|
|
51
|
+
if (!isObject(currentError)) break;
|
|
52
|
+
extractedError = currentError;
|
|
53
|
+
}
|
|
54
|
+
return extractedError.message;
|
|
55
|
+
};
|
|
56
|
+
const getEyeIcon = (options) => {
|
|
57
|
+
const { classNames, iconType, renderIconProps, withEyeIcon } = options;
|
|
58
|
+
if (!withEyeIcon) return null;
|
|
59
|
+
if (withEyeIcon === true) return {
|
|
60
|
+
closed: createElement(EyeIconClosed, { className: cnMerge("size-full", classNames?.eyeIcon) }),
|
|
61
|
+
open: createElement(EyeIconOpen, { className: cnMerge("size-full", classNames?.eyeIcon) })
|
|
62
|
+
}[iconType];
|
|
63
|
+
if (withEyeIcon.renderIcon) return withEyeIcon.renderIcon(renderIconProps);
|
|
64
|
+
if (withEyeIcon[iconType]) return withEyeIcon[iconType];
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/components/ui/form/form-context.ts
|
|
70
|
+
const useFormMethodsContext = (options = {}) => {
|
|
71
|
+
const { strict = true } = options;
|
|
72
|
+
const formContext = useFormContext();
|
|
73
|
+
if (strict && !formContext) throw new ContextError(`useFormRootContext returned "null". Did you forget to wrap the necessary components within FormRoot?`);
|
|
74
|
+
return formContext;
|
|
75
|
+
};
|
|
76
|
+
const [LaxFormRootProvider, useLaxFormRootContext] = createCustomContext({
|
|
77
|
+
defaultValue: null,
|
|
78
|
+
hookName: "useLaxFormRootContext",
|
|
79
|
+
name: "LaxFormRootContext",
|
|
80
|
+
providerName: "FormRoot",
|
|
81
|
+
strict: false
|
|
82
|
+
});
|
|
83
|
+
const [StrictFormFieldProvider, useStrictFormFieldContext] = createCustomContext({
|
|
84
|
+
hookName: "useFormFieldContext",
|
|
85
|
+
name: "StrictFormFieldContext",
|
|
86
|
+
providerName: "FormField"
|
|
87
|
+
});
|
|
88
|
+
const [LaxFormFieldProvider, useLaxFormFieldContext] = createCustomContext({
|
|
89
|
+
defaultValue: null,
|
|
90
|
+
hookName: "useLaxFormFieldContext",
|
|
91
|
+
name: "LaxFormFieldContext",
|
|
92
|
+
providerName: "FormField",
|
|
93
|
+
strict: false
|
|
94
|
+
});
|
|
95
|
+
const useLaxFormFieldState = (options) => {
|
|
96
|
+
const { control = options?.control } = useFormMethodsContext({ strict: false }) ?? {};
|
|
97
|
+
const { name = options?.name } = useLaxFormFieldContext() ?? {};
|
|
98
|
+
const { disabled, errors } = (control ? useFormState : () => ({}))({
|
|
99
|
+
control,
|
|
100
|
+
name
|
|
101
|
+
});
|
|
102
|
+
const errorMessage = getFieldErrorMessage({
|
|
103
|
+
errors,
|
|
104
|
+
fieldName: name,
|
|
105
|
+
type: "regular"
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
errors,
|
|
109
|
+
isDisabled: disabled,
|
|
110
|
+
isInvalid: Boolean(errorMessage)
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/components/ui/form/form.tsx
|
|
116
|
+
function FormRoot(props) {
|
|
117
|
+
const { children, className, methods, withEyeIcon,...restOfProps } = props;
|
|
118
|
+
const formContextValue = useMemo(() => ({ withEyeIcon }), [withEyeIcon]);
|
|
119
|
+
return /* @__PURE__ */ jsx(FormProvider, {
|
|
120
|
+
...methods,
|
|
121
|
+
children: /* @__PURE__ */ jsx(LaxFormRootProvider, {
|
|
122
|
+
value: formContextValue,
|
|
123
|
+
children: /* @__PURE__ */ jsx("form", {
|
|
124
|
+
className: cnMerge("flex flex-col", className),
|
|
125
|
+
...restOfProps,
|
|
126
|
+
"data-scope": "form",
|
|
127
|
+
"data-part": "root",
|
|
128
|
+
"data-slot": "form-root",
|
|
129
|
+
children
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function FormField(props) {
|
|
135
|
+
const { children, className, name, withWrapper = true } = props;
|
|
136
|
+
const { isDisabled, isInvalid } = useLaxFormFieldState({ name });
|
|
137
|
+
const uniqueId = useId();
|
|
138
|
+
const fieldContextValue = useMemo(() => ({
|
|
139
|
+
formDescriptionId: `${name}-(${uniqueId})-form-item-description`,
|
|
140
|
+
formItemId: `${name}-(${uniqueId})-form-item`,
|
|
141
|
+
formMessageId: `${name}-(${uniqueId})-form-item-message`,
|
|
142
|
+
name
|
|
143
|
+
}), [name, uniqueId]);
|
|
144
|
+
const WrapperElement = withWrapper ? "div" : Fragment;
|
|
145
|
+
const wrapperElementProps = withWrapper && {
|
|
146
|
+
className: cnMerge("flex flex-col gap-2", className),
|
|
147
|
+
"data-part": "field",
|
|
148
|
+
"data-scope": "form",
|
|
149
|
+
"data-slot": "form-field",
|
|
150
|
+
"data-disabled": dataAttr(isDisabled),
|
|
151
|
+
"data-invalid": dataAttr(isInvalid)
|
|
152
|
+
};
|
|
153
|
+
return /* @__PURE__ */ jsx(StrictFormFieldProvider, {
|
|
154
|
+
value: fieldContextValue,
|
|
155
|
+
children: /* @__PURE__ */ jsx(LaxFormFieldProvider, {
|
|
156
|
+
value: fieldContextValue,
|
|
157
|
+
children: /* @__PURE__ */ jsx(WrapperElement, {
|
|
158
|
+
...wrapperElementProps,
|
|
159
|
+
children
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function FormFieldController(props) {
|
|
165
|
+
const { control } = useFormMethodsContext();
|
|
166
|
+
const { name } = useStrictFormFieldContext();
|
|
167
|
+
const { render,...restOfProps } = props;
|
|
168
|
+
return /* @__PURE__ */ jsx(Controller, {
|
|
169
|
+
name,
|
|
170
|
+
control,
|
|
171
|
+
render,
|
|
172
|
+
...restOfProps
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function FormFieldControlledField(props) {
|
|
176
|
+
const { name } = props;
|
|
177
|
+
const uniqueId = useId();
|
|
178
|
+
const fieldContextValue = useMemo(() => ({
|
|
179
|
+
formDescriptionId: `${name}-(${uniqueId})-form-item-description`,
|
|
180
|
+
formItemId: `${name}-(${uniqueId})-form-item`,
|
|
181
|
+
formMessageId: `${name}-(${uniqueId})-form-item-message`,
|
|
182
|
+
name
|
|
183
|
+
}), [name, uniqueId]);
|
|
184
|
+
return /* @__PURE__ */ jsx(StrictFormFieldProvider, {
|
|
185
|
+
value: fieldContextValue,
|
|
186
|
+
children: /* @__PURE__ */ jsx(LaxFormFieldProvider, {
|
|
187
|
+
value: fieldContextValue,
|
|
188
|
+
children: /* @__PURE__ */ jsx(Controller, { ...props })
|
|
189
|
+
})
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function FormFieldContext(props) {
|
|
193
|
+
const { children, render } = props;
|
|
194
|
+
const fieldContextValues = useStrictFormFieldContext();
|
|
195
|
+
if (typeof children === "function") return children(fieldContextValues);
|
|
196
|
+
return render(fieldContextValues);
|
|
197
|
+
}
|
|
198
|
+
function FormLabel(props) {
|
|
199
|
+
const fieldContextValues = useStrictFormFieldContext();
|
|
200
|
+
const { children, htmlFor = fieldContextValues.formItemId,...restOfProps } = props;
|
|
201
|
+
const { isDisabled, isInvalid } = useLaxFormFieldState({ name: fieldContextValues.name });
|
|
202
|
+
return /* @__PURE__ */ jsx("label", {
|
|
203
|
+
"data-scope": "form",
|
|
204
|
+
"data-part": "label",
|
|
205
|
+
"data-slot": "form-label",
|
|
206
|
+
"data-disabled": dataAttr(isDisabled),
|
|
207
|
+
"data-invalid": dataAttr(isInvalid),
|
|
208
|
+
htmlFor,
|
|
209
|
+
...restOfProps,
|
|
210
|
+
children
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function FormInputGroup(props) {
|
|
214
|
+
const { children, className,...restOfProps } = props;
|
|
215
|
+
const { isDisabled, isInvalid } = useLaxFormFieldState();
|
|
216
|
+
const { regularChildren, slots: [leftItemSlot, rightItemSlot] } = getMultipleSlots(children, [FormInputLeftItem, FormInputRightItem]);
|
|
217
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
218
|
+
"data-scope": "form",
|
|
219
|
+
"data-part": "input-group",
|
|
220
|
+
"data-slot": "form-input-group",
|
|
221
|
+
"data-invalid": dataAttr(isInvalid),
|
|
222
|
+
"data-disabled": dataAttr(isDisabled),
|
|
223
|
+
className: cnMerge("flex items-center justify-between gap-2", className),
|
|
224
|
+
...restOfProps,
|
|
225
|
+
children: [
|
|
226
|
+
leftItemSlot,
|
|
227
|
+
regularChildren,
|
|
228
|
+
rightItemSlot
|
|
229
|
+
]
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function FormInputLeftItem(props) {
|
|
233
|
+
const { as: Element = "span", children, className,...restOfProps } = props;
|
|
234
|
+
return /* @__PURE__ */ jsx(Element, {
|
|
235
|
+
"data-scope": "form",
|
|
236
|
+
"data-part": "left-item",
|
|
237
|
+
"data-slot": "form-left-item",
|
|
238
|
+
className: cnMerge("inline-flex items-center justify-center", className),
|
|
239
|
+
...restOfProps,
|
|
240
|
+
children
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
FormInputLeftItem.slotSymbol = Symbol("input-left-item");
|
|
244
|
+
function FormInputRightItem(props) {
|
|
245
|
+
const { as: Element = "span", children, className,...restOfProps } = props;
|
|
246
|
+
return /* @__PURE__ */ jsx(Element, {
|
|
247
|
+
"data-scope": "form",
|
|
248
|
+
"data-part": "right-item",
|
|
249
|
+
"data-slot": "form-right-item",
|
|
250
|
+
className: cnMerge("inline-flex items-center justify-center", className),
|
|
251
|
+
...restOfProps,
|
|
252
|
+
children
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
FormInputRightItem.slotSymbol = Symbol("input-right-item");
|
|
256
|
+
const inputTypesWithoutFullWith = new Set(["checkbox", "radio"]);
|
|
257
|
+
function FormInputPrimitive(props) {
|
|
258
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
259
|
+
const formRootContextValues = useLaxFormRootContext();
|
|
260
|
+
const { className, classNames, control, fieldState, id = fieldContextValues?.formItemId, name = fieldContextValues?.name, rules, type = "text", withEyeIcon = formRootContextValues?.withEyeIcon ?? true,...restOfProps } = props;
|
|
261
|
+
const fieldStateFromLaxFormField = useLaxFormFieldState({
|
|
262
|
+
control,
|
|
263
|
+
name
|
|
264
|
+
});
|
|
265
|
+
const { isDisabled, isInvalid } = fieldState ?? fieldStateFromLaxFormField;
|
|
266
|
+
const [isPasswordVisible, toggleVisibility] = useToggle(false);
|
|
267
|
+
const shouldHaveEyeIcon = withEyeIcon && type === "password";
|
|
268
|
+
const WrapperElement = shouldHaveEyeIcon ? FormInputGroup : Fragment;
|
|
269
|
+
const wrapperElementProps = shouldHaveEyeIcon && { className: cnMerge("w-full", classNames?.inputGroup, isInvalid && classNames?.error) };
|
|
270
|
+
const { register } = useFormMethodsContext({ strict: false }) ?? {};
|
|
271
|
+
const eyeIcon = getEyeIcon({
|
|
272
|
+
classNames,
|
|
273
|
+
iconType: isPasswordVisible ? "closed" : "open",
|
|
274
|
+
renderIconProps: { isPasswordVisible },
|
|
275
|
+
withEyeIcon
|
|
276
|
+
});
|
|
277
|
+
return /* @__PURE__ */ jsxs(WrapperElement, {
|
|
278
|
+
...wrapperElementProps,
|
|
279
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
280
|
+
"data-scope": "form",
|
|
281
|
+
"data-part": "input",
|
|
282
|
+
"data-slot": "form-input",
|
|
283
|
+
"aria-describedby": !isInvalid ? fieldContextValues?.formDescriptionId : `${fieldContextValues?.formDescriptionId} ${fieldContextValues?.formMessageId}`,
|
|
284
|
+
"aria-invalid": dataAttr(isInvalid),
|
|
285
|
+
"data-invalid": dataAttr(isInvalid),
|
|
286
|
+
"data-disabled": dataAttr(isDisabled),
|
|
287
|
+
id,
|
|
288
|
+
name,
|
|
289
|
+
type: type === "password" && isPasswordVisible ? "text" : type,
|
|
290
|
+
className: cnMerge(!inputTypesWithoutFullWith.has(type) && "flex w-full", `bg-transparent text-sm file:border-0 file:bg-transparent
|
|
291
|
+
placeholder:text-zu-muted-foreground focus-visible:outline-hidden
|
|
292
|
+
disabled:cursor-not-allowed disabled:opacity-50`, className, classNames?.input, type !== "password" && isInvalid && classNames?.error),
|
|
293
|
+
...Boolean(name) && register?.(name, rules),
|
|
294
|
+
...restOfProps
|
|
295
|
+
}), shouldHaveEyeIcon && /* @__PURE__ */ jsx(FormInputRightItem, {
|
|
296
|
+
as: "button",
|
|
297
|
+
type: "button",
|
|
298
|
+
onClick: toggleVisibility,
|
|
299
|
+
className: "size-5 shrink-0 lg:size-6",
|
|
300
|
+
children: eyeIcon
|
|
301
|
+
})]
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function FormTextAreaPrimitive(props) {
|
|
305
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
306
|
+
const { className, classNames, control, fieldState, id = fieldContextValues?.formItemId, name = fieldContextValues?.name, rules,...restOfProps } = props;
|
|
307
|
+
const fieldStateFromLaxFormField = useLaxFormFieldState({
|
|
308
|
+
control,
|
|
309
|
+
name
|
|
310
|
+
});
|
|
311
|
+
const { isDisabled, isInvalid } = fieldState ?? fieldStateFromLaxFormField;
|
|
312
|
+
const { register } = useFormMethodsContext({ strict: false }) ?? {};
|
|
313
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
314
|
+
"data-scope": "form",
|
|
315
|
+
"data-part": "textarea",
|
|
316
|
+
"data-slot": "form-textarea",
|
|
317
|
+
"aria-describedby": !isInvalid ? fieldContextValues?.formDescriptionId : `${fieldContextValues?.formDescriptionId} ${fieldContextValues?.formMessageId}`,
|
|
318
|
+
"aria-invalid": dataAttr(isInvalid),
|
|
319
|
+
"data-disabled": dataAttr(isDisabled),
|
|
320
|
+
"data-invalid": dataAttr(isInvalid),
|
|
321
|
+
id,
|
|
322
|
+
name,
|
|
323
|
+
className: cnMerge(`w-full bg-transparent text-sm placeholder:text-zu-muted-foreground
|
|
324
|
+
focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50`, className, classNames?.base, isInvalid && classNames?.error),
|
|
325
|
+
...Boolean(name) && register?.(name, rules),
|
|
326
|
+
...restOfProps
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function FormSelectPrimitive(props) {
|
|
330
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
331
|
+
const { className, classNames, control, fieldState, id = fieldContextValues?.formItemId, name = fieldContextValues?.name, rules,...restOfProps } = props;
|
|
332
|
+
const fieldStateFromLaxFormField = useLaxFormFieldState({
|
|
333
|
+
control,
|
|
334
|
+
name
|
|
335
|
+
});
|
|
336
|
+
const { isDisabled, isInvalid } = fieldState ?? fieldStateFromLaxFormField;
|
|
337
|
+
const { register } = useFormMethodsContext({ strict: false }) ?? {};
|
|
338
|
+
return /* @__PURE__ */ jsx("select", {
|
|
339
|
+
defaultValue: "",
|
|
340
|
+
"data-scope": "form",
|
|
341
|
+
"data-part": "select",
|
|
342
|
+
"data-slot": "form-select",
|
|
343
|
+
"aria-describedby": !isInvalid ? fieldContextValues?.formDescriptionId : `${fieldContextValues?.formDescriptionId} ${fieldContextValues?.formMessageId}`,
|
|
344
|
+
"aria-invalid": dataAttr(isInvalid),
|
|
345
|
+
"data-disabled": dataAttr(isDisabled),
|
|
346
|
+
"data-invalid": dataAttr(isInvalid),
|
|
347
|
+
id,
|
|
348
|
+
name,
|
|
349
|
+
className: cnMerge(`w-full bg-transparent text-sm placeholder:text-zu-muted-foreground
|
|
350
|
+
focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50`, className, classNames?.base, isInvalid && classNames?.error),
|
|
351
|
+
...Boolean(name) && register?.(name, rules),
|
|
352
|
+
...restOfProps
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
const InputTypeMap = defineEnum({
|
|
356
|
+
select: FormSelectPrimitive,
|
|
357
|
+
textarea: FormTextAreaPrimitive
|
|
358
|
+
});
|
|
359
|
+
function FormInput(props) {
|
|
360
|
+
const { onBlur, onChange, ref, rules, type,...restOfProps } = props;
|
|
361
|
+
const { name } = useStrictFormFieldContext();
|
|
362
|
+
const { register } = useFormMethodsContext();
|
|
363
|
+
const SelectedInput = type === "textarea" || type === "select" ? InputTypeMap[type] : FormInputPrimitive;
|
|
364
|
+
const registerProps = name ? register(name, rules) : null;
|
|
365
|
+
return /* @__PURE__ */ jsx(SelectedInput, {
|
|
366
|
+
type,
|
|
367
|
+
name,
|
|
368
|
+
...registerProps,
|
|
369
|
+
...restOfProps,
|
|
370
|
+
ref: composeRefs(registerProps?.ref, ref),
|
|
371
|
+
onChange: composeTwoEventHandlers(registerProps?.onChange, onChange),
|
|
372
|
+
onBlur: composeTwoEventHandlers(registerProps?.onBlur, onBlur)
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function FormTextArea(props) {
|
|
376
|
+
return /* @__PURE__ */ jsx(FormInput, {
|
|
377
|
+
...props,
|
|
378
|
+
type: "textarea"
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
function FormSelect(props) {
|
|
382
|
+
return /* @__PURE__ */ jsx(FormInput, {
|
|
383
|
+
...props,
|
|
384
|
+
type: "select"
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
function FormDescription(props) {
|
|
388
|
+
const { className,...restOfProps } = props;
|
|
389
|
+
const { formDescriptionId } = useLaxFormFieldContext() ?? {};
|
|
390
|
+
return /* @__PURE__ */ jsx("p", {
|
|
391
|
+
id: formDescriptionId,
|
|
392
|
+
className: cnMerge("text-[12px]", className),
|
|
393
|
+
...restOfProps
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
const FormErrorMessagePrimitive = (props) => {
|
|
397
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
398
|
+
const rootContextValues = useFormMethodsContext({ strict: false });
|
|
399
|
+
const { children, className, classNames, control = rootContextValues?.control, disableErrorAnimation = false, disableScrollToErrorField = false, fieldName = fieldContextValues?.name, renderItem, type = "regular" } = props;
|
|
400
|
+
const { errors } = useLaxFormFieldState({
|
|
401
|
+
control,
|
|
402
|
+
name: fieldName
|
|
403
|
+
});
|
|
404
|
+
const { formMessageId } = useLaxFormFieldContext() ?? {};
|
|
405
|
+
const containerRef = useRef(null);
|
|
406
|
+
const errorAnimationClass = classNames?.errorMessageAnimation ?? "animate-shake";
|
|
407
|
+
const getErrorElements = useCallbackRef(() => containerRef.current?.children ?? []);
|
|
408
|
+
useEffect(() => {
|
|
409
|
+
if (disableErrorAnimation) return;
|
|
410
|
+
if (!errors || Object.keys(errors).length === 0) return;
|
|
411
|
+
const errorMessageElements = getErrorElements();
|
|
412
|
+
if (errorMessageElements.length === 0) return;
|
|
413
|
+
const controller = new AbortController();
|
|
414
|
+
for (const element of errorMessageElements) {
|
|
415
|
+
element.classList.add(errorAnimationClass);
|
|
416
|
+
const onAnimationEnd = () => element.classList.remove(errorAnimationClass);
|
|
417
|
+
on("animationend", element, onAnimationEnd, {
|
|
418
|
+
once: true,
|
|
419
|
+
signal: controller.signal
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
return () => {
|
|
423
|
+
controller.abort();
|
|
424
|
+
};
|
|
425
|
+
}, [
|
|
426
|
+
disableErrorAnimation,
|
|
427
|
+
errorAnimationClass,
|
|
428
|
+
errors,
|
|
429
|
+
getErrorElements
|
|
430
|
+
]);
|
|
431
|
+
useEffect(() => {
|
|
432
|
+
if (disableScrollToErrorField) return;
|
|
433
|
+
if (!errors || Object.keys(errors).length === 0) return;
|
|
434
|
+
const errorMessageElements = getErrorElements();
|
|
435
|
+
if (errorMessageElements.length === 0) return;
|
|
436
|
+
const firstErrorElement = errorMessageElements[0];
|
|
437
|
+
if (!firstErrorElement) return;
|
|
438
|
+
if (document.querySelector(`[name='${fieldName}']`)?.matches(":is(input, select, textarea, [contenteditable='true'])")) return;
|
|
439
|
+
const frameID = requestAnimationFrame(() => {
|
|
440
|
+
const elementRect = firstErrorElement.getBoundingClientRect();
|
|
441
|
+
if (elementRect.top === 0) return;
|
|
442
|
+
const topWithOffset = elementRect.top - 100;
|
|
443
|
+
window.scrollTo({
|
|
444
|
+
behavior: "smooth",
|
|
445
|
+
top: window.scrollY + topWithOffset
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
return () => {
|
|
449
|
+
cancelAnimationFrame(frameID);
|
|
450
|
+
};
|
|
451
|
+
}, [
|
|
452
|
+
disableScrollToErrorField,
|
|
453
|
+
fieldName,
|
|
454
|
+
errors,
|
|
455
|
+
getErrorElements
|
|
456
|
+
]);
|
|
457
|
+
const fieldErrorMessage = getFieldErrorMessage({
|
|
458
|
+
errors,
|
|
459
|
+
fieldName,
|
|
460
|
+
type
|
|
461
|
+
});
|
|
462
|
+
if (!fieldErrorMessage) return null;
|
|
463
|
+
const errorMessageArray = toArray(fieldErrorMessage);
|
|
464
|
+
if (errorMessageArray.length === 0) return null;
|
|
465
|
+
const getRenderProps = (options) => {
|
|
466
|
+
const { index } = options;
|
|
467
|
+
return {
|
|
468
|
+
className: cnMerge(className, classNames?.errorMessage),
|
|
469
|
+
"data-index": index,
|
|
470
|
+
"data-part": "error-message",
|
|
471
|
+
"data-scope": "form",
|
|
472
|
+
"data-slot": "form-error-message",
|
|
473
|
+
id: formMessageId
|
|
474
|
+
};
|
|
475
|
+
};
|
|
476
|
+
const getRenderState = (options) => {
|
|
477
|
+
const { errorMessage, index } = options;
|
|
478
|
+
return {
|
|
479
|
+
errorMessage,
|
|
480
|
+
errorMessageArray,
|
|
481
|
+
index
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
const selectedChildren = typeof children === "function" ? children : renderItem;
|
|
485
|
+
return /* @__PURE__ */ jsx(ForWithWrapper, {
|
|
486
|
+
ref: containerRef,
|
|
487
|
+
className: cnMerge("flex flex-col", classNames?.container),
|
|
488
|
+
"data-part": "error-message-container",
|
|
489
|
+
"data-scope": "form",
|
|
490
|
+
"data-slot": "form-error-message-container",
|
|
491
|
+
each: errorMessageArray,
|
|
492
|
+
renderItem: (errorMessage, index) => {
|
|
493
|
+
return selectedChildren({
|
|
494
|
+
props: getRenderProps({ index }),
|
|
495
|
+
state: getRenderState({
|
|
496
|
+
errorMessage,
|
|
497
|
+
index
|
|
498
|
+
})
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
};
|
|
503
|
+
function FormErrorMessage(props) {
|
|
504
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
505
|
+
const { className, errorField = fieldContextValues?.name, type = "regular" } = props;
|
|
506
|
+
const { control } = useFormMethodsContext();
|
|
507
|
+
return /* @__PURE__ */ jsx(FormErrorMessagePrimitive, {
|
|
508
|
+
control,
|
|
509
|
+
fieldName: errorField,
|
|
510
|
+
type,
|
|
511
|
+
renderItem: ({ props: renderProps, state }) => /* @__PURE__ */ jsx("li", {
|
|
512
|
+
...renderProps,
|
|
513
|
+
className: cnMerge("text-[13px] text-zu-destructive", "data-[index=0]:mt-1", renderProps.className, className),
|
|
514
|
+
children: state.errorMessage
|
|
515
|
+
}, state.errorMessage)
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
function FormSubmit(props) {
|
|
519
|
+
const { as: Element = "button", asChild, children, type = "submit",...restOfProps } = props;
|
|
520
|
+
const Component$1 = asChild ? SlotRoot : Element;
|
|
521
|
+
return /* @__PURE__ */ jsx(Component$1, {
|
|
522
|
+
"data-part": "submit",
|
|
523
|
+
"data-scope": "form",
|
|
524
|
+
"data-slot": "form-submit",
|
|
525
|
+
type,
|
|
526
|
+
...restOfProps,
|
|
527
|
+
children
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function FormSubscribeToFieldValue(props) {
|
|
531
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
532
|
+
const { children, name = fieldContextValues?.name, render } = props;
|
|
533
|
+
const { control } = useFormMethodsContext();
|
|
534
|
+
const formValue = useWatch({
|
|
535
|
+
control,
|
|
536
|
+
name
|
|
537
|
+
});
|
|
538
|
+
return (typeof children === "function" ? children : render)({ value: formValue });
|
|
539
|
+
}
|
|
540
|
+
function FormSubscribeToFormState(props) {
|
|
541
|
+
const fieldContextValues = useLaxFormFieldContext();
|
|
542
|
+
const { children, control, name = fieldContextValues?.name, render } = props;
|
|
543
|
+
const formState = useFormState({
|
|
544
|
+
control,
|
|
545
|
+
name
|
|
546
|
+
});
|
|
547
|
+
return (typeof children === "function" ? children : render)(formState);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
//#endregion
|
|
551
|
+
//#region src/components/ui/form/form-parts.ts
|
|
552
|
+
var form_parts_exports = __export({
|
|
553
|
+
ControlledField: () => FormFieldControlledField,
|
|
554
|
+
Description: () => FormDescription,
|
|
555
|
+
ErrorMessage: () => FormErrorMessage,
|
|
556
|
+
ErrorMessagePrimitive: () => FormErrorMessagePrimitive,
|
|
557
|
+
Field: () => FormField,
|
|
558
|
+
FieldContext: () => FormFieldContext,
|
|
559
|
+
FieldController: () => FormFieldController,
|
|
560
|
+
Input: () => FormInput,
|
|
561
|
+
InputGroup: () => FormInputGroup,
|
|
562
|
+
InputLeftItem: () => FormInputLeftItem,
|
|
563
|
+
InputPrimitive: () => FormInputPrimitive,
|
|
564
|
+
InputRightItem: () => FormInputRightItem,
|
|
565
|
+
Label: () => FormLabel,
|
|
566
|
+
Root: () => FormRoot,
|
|
567
|
+
Select: () => FormSelect,
|
|
568
|
+
Submit: () => FormSubmit,
|
|
569
|
+
SubscribeToFieldValue: () => FormSubscribeToFieldValue,
|
|
570
|
+
SubscribeToFormState: () => FormSubscribeToFormState,
|
|
571
|
+
TextArea: () => FormTextArea,
|
|
572
|
+
TextAreaPrimitive: () => FormTextAreaPrimitive
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
//#endregion
|
|
576
|
+
export { form_parts_exports as Form, FormDescription, FormErrorMessage, FormErrorMessagePrimitive, FormField, FormFieldContext, FormFieldControlledField, FormFieldController, FormInput, FormInputGroup, FormInputLeftItem, FormInputPrimitive, FormInputRightItem, FormLabel, FormRoot, FormSelect, FormSelectPrimitive, FormSubmit, FormSubscribeToFieldValue, FormSubscribeToFormState, FormTextArea, FormTextAreaPrimitive, useStrictFormFieldContext as useFormFieldContext, useFormRootContext };
|
|
577
|
+
//# sourceMappingURL=index.js.map
|