@mittwald/flow-react-components 1.5.0-next.13 → 1.5.0-next.15
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/AGENTS.md +9 -4
- package/dist/assets/component-index.json +1 -1
- package/dist/assets/doc-properties.json +1 -1
- package/dist/js/packages/components/src/components/Autocomplete/Autocomplete.mjs +14 -7
- package/dist/js/packages/components/src/components/Autocomplete/Autocomplete.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Checkbox/Checkbox.mjs +3 -3
- package/dist/js/packages/components/src/components/Checkbox/Checkbox.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CheckboxButton/CheckboxButton.mjs +3 -3
- package/dist/js/packages/components/src/components/CheckboxButton/CheckboxButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CheckboxGroup/CheckboxGroup.mjs +3 -3
- package/dist/js/packages/components/src/components/CheckboxGroup/CheckboxGroup.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.mjs +24 -10
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ComboBox/ComboBox.mjs +3 -3
- package/dist/js/packages/components/src/components/ComboBox/ComboBox.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DatePicker/DatePicker.mjs +3 -3
- package/dist/js/packages/components/src/components/DatePicker/DatePicker.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DateRangePicker/DateRangePicker.mjs +3 -2
- package/dist/js/packages/components/src/components/DateRangePicker/DateRangePicker.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FieldError/FieldError.mjs +40 -31
- package/dist/js/packages/components/src/components/FieldError/FieldError.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileDropZone/FileDropZone.mjs +8 -6
- package/dist/js/packages/components/src/components/FileDropZone/FileDropZone.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileField/FileField.mjs +3 -3
- package/dist/js/packages/components/src/components/FileField/FileField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/NumberField/NumberField.mjs +3 -2
- package/dist/js/packages/components/src/components/NumberField/NumberField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs +42 -19
- package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.mjs +2 -2
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/usePolicyValidationResult.mjs +12 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/usePolicyValidationResult.mjs.map +1 -1
- package/dist/js/packages/components/src/components/RadioGroup/RadioGroup.mjs +3 -2
- package/dist/js/packages/components/src/components/RadioGroup/RadioGroup.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Rating/Rating.mjs +3 -2
- package/dist/js/packages/components/src/components/Rating/Rating.mjs.map +1 -1
- package/dist/js/packages/components/src/components/SearchField/SearchField.mjs +3 -3
- package/dist/js/packages/components/src/components/SearchField/SearchField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/SegmentedControl/SegmentedControl.mjs +3 -2
- package/dist/js/packages/components/src/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Select/Select.mjs +3 -3
- package/dist/js/packages/components/src/components/Select/Select.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Slider/Slider.mjs +4 -3
- package/dist/js/packages/components/src/components/Slider/Slider.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Switch/Switch.mjs +3 -2
- package/dist/js/packages/components/src/components/Switch/Switch.mjs.map +1 -1
- package/dist/js/packages/components/src/components/TextArea/TextArea.mjs +3 -3
- package/dist/js/packages/components/src/components/TextArea/TextArea.mjs.map +1 -1
- package/dist/js/packages/components/src/components/TextField/TextField.mjs +3 -3
- package/dist/js/packages/components/src/components/TextField/TextField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/TimeField/TimeField.mjs +3 -2
- package/dist/js/packages/components/src/components/TimeField/TimeField.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/hooks/fieldErrorRenderedContext.mjs +16 -0
- package/dist/js/packages/components/src/lib/hooks/fieldErrorRenderedContext.mjs.map +1 -0
- package/dist/js/packages/components/src/lib/hooks/useFieldComponent.mjs +8 -7
- package/dist/js/packages/components/src/lib/hooks/useFieldComponent.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/hooks/useFieldError.mjs +34 -21
- package/dist/js/packages/components/src/lib/hooks/useFieldError.mjs.map +1 -1
- package/dist/types/components/FileField/FileField.d.ts +1 -1
- package/dist/types/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.d.ts +5 -0
- package/dist/types/lib/hooks/fieldErrorRenderedContext.d.ts +1 -0
- package/dist/types/lib/hooks/useFieldComponent.d.ts +15 -4
- package/dist/types/lib/hooks/useFieldError.d.ts +7 -1
- package/package.json +10 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldError.mjs","names":[],"sources":["../../../../../../../src/components/FieldError/FieldError.tsx"],"sourcesContent":["import React, {\n type PropsWithChildren,\n
|
|
1
|
+
{"version":3,"file":"FieldError.mjs","names":[],"sources":["../../../../../../../src/components/FieldError/FieldError.tsx"],"sourcesContent":["import React, {\n type PropsWithChildren,\n useContext,\n useLayoutEffect,\n} from \"react\";\nimport styles from \"./FieldError.module.scss\";\nimport * as Aria from \"react-aria-components\";\nimport { FieldErrorContext, TextContext } from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { AlertText } from \"@/components/AlertText\";\nimport { Alert } from \"@/components/Alert\";\nimport { Heading } from \"@/components/Heading\";\nimport { FieldErrorRenderedContext } from \"@/lib/hooks/fieldErrorRenderedContext\";\nimport { useObjectRef } from \"react-aria\";\n\nexport interface FieldErrorProps\n extends\n PropsWithChildren<Omit<Aria.FieldErrorProps, \"children\">>,\n FlowComponentProps {\n /** @internal */\n renderAlert?: boolean;\n}\n\n/** @flr-generate all */\nexport const FieldError = flowComponent(\"FieldError\", (props) => {\n const { children, className, ref, renderAlert, ...rest } = props;\n\n const rootClassName = clsx(styles.fieldError, className);\n const fieldValidation = useContext(FieldErrorContext);\n const reportRendered = useContext(FieldErrorRenderedContext);\n const hasChildren = React.Children.count(children) >= 1;\n\n // Inside a field the field decides whether there is an error – children only\n // provide its message. Without a field, children are the error.\n const isInvalid = fieldValidation ? fieldValidation.isInvalid : hasChildren;\n\n // Never mutate the context's errors: for a valid field react-aria hands out\n // one module-level array shared by every field of the page.\n const message = hasChildren\n ? children\n : fieldValidation?.validationErrors.at(-1);\n\n const errorState = {\n isInvalid,\n validationDetails: fieldValidation?.validationDetails ?? {\n badInput: false,\n customError: isInvalid,\n patternMismatch: false,\n rangeOverflow: false,\n rangeUnderflow: false,\n stepMismatch: false,\n tooLong: false,\n tooShort: false,\n typeMismatch: false,\n valid: !isInvalid,\n valueMissing: false,\n },\n validationErrors: message ? [message] : [],\n };\n\n // Report what is actually in the document: inside a collection (`Select`,\n // `ComboBox`) react-aria renders the children a second time into a hidden\n // collection document, where no field context exists and no id resolves.\n const localRef = useObjectRef(ref);\n useLayoutEffect(() => {\n const element = localRef.current;\n if (!reportRendered || !isInvalid || !element?.isConnected || !element.id) {\n return;\n }\n reportRendered(element.id);\n return () => reportRendered(undefined);\n }, [reportRendered, isInvalid, rest.id, localRef]);\n\n if (!isInvalid) {\n return undefined;\n }\n\n return (\n <Aria.Provider values={[[TextContext, { slot: undefined }]]}>\n <FieldErrorContext value={errorState as never}>\n <Aria.FieldError ref={localRef} {...rest} className={rootClassName}>\n {({ validationErrors }) => {\n return renderAlert ? (\n <Alert status=\"danger\">\n <Heading>{validationErrors}</Heading>\n </Alert>\n ) : (\n <AlertText status=\"danger\">{validationErrors}</AlertText>\n );\n }}\n </Aria.FieldError>\n </FieldErrorContext>\n </Aria.Provider>\n );\n});\n\nexport default FieldError;\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,IAAa,aAAa,cAAc,eAAe,UAAU;CAC/D,MAAM,EAAE,UAAU,WAAW,KAAK,aAAa,GAAG,SAAS;CAE3D,MAAM,gBAAgB,KAAK,0BAAO,YAAY,SAAS;CACvD,MAAM,kBAAkB,WAAW,iBAAiB;CACpD,MAAM,iBAAiB,WAAW,yBAAyB;CAC3D,MAAM,cAAc,MAAM,SAAS,MAAM,QAAQ,KAAK;CAItD,MAAM,YAAY,kBAAkB,gBAAgB,YAAY;CAIhE,MAAM,UAAU,cACZ,WACA,iBAAiB,iBAAiB,GAAG,EAAE;CAE3C,MAAM,aAAa;EACjB;EACA,mBAAmB,iBAAiB,qBAAqB;GACvD,UAAU;GACV,aAAa;GACb,iBAAiB;GACjB,eAAe;GACf,gBAAgB;GAChB,cAAc;GACd,SAAS;GACT,UAAU;GACV,cAAc;GACd,OAAO,CAAC;GACR,cAAc;EAChB;EACA,kBAAkB,UAAU,CAAC,OAAO,IAAI,CAAC;CAC3C;CAKA,MAAM,WAAW,aAAa,GAAG;CACjC,sBAAsB;EACpB,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,SAAS,eAAe,CAAC,QAAQ,IACrE;EAEF,eAAe,QAAQ,EAAE;EACzB,aAAa,eAAe,KAAA,CAAS;CACvC,GAAG;EAAC;EAAgB;EAAW,KAAK;EAAI;CAAQ,CAAC;CAEjD,IAAI,CAAC,WACH;CAGF,OACE,oBAAC,KAAK,UAAN;EAAe,QAAQ,CAAC,CAAC,aAAa,EAAE,MAAM,KAAA,EAAU,CAAC,CAAC;EACxD,UAAA,oBAAC,mBAAD;GAAmB,OAAO;GACxB,UAAA,oBAAC,KAAK,YAAN;IAAiB,KAAK;IAAU,GAAI;IAAM,WAAW;IACjD,WAAA,EAAE,uBAAuB;KACzB,OAAO,cACL,oBAAC,OAAD;MAAO,QAAO;MACZ,UAAA,oBAAC,SAAD,EAAA,UAAU,iBAA0B,CAAA;KAC/B,CAAA,IAEP,oBAAC,WAAD;MAAW,QAAO;MAAU,UAAA;KAA4B,CAAA;IAE5D;GACe,CAAA;EACA,CAAA;CACN,CAAA;AAEnB,CAAC"}
|
|
@@ -14,7 +14,7 @@ import * as Aria from "react-aria-components";
|
|
|
14
14
|
/** @flr-generate all */
|
|
15
15
|
var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
16
16
|
const { multiple, accept, className, onChange: onChangeDropZone, children, name, isDisabled, isReadOnly } = props;
|
|
17
|
-
const { FieldErrorView, FieldErrorCaptureContext,
|
|
17
|
+
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext } = useFieldComponent(props, "FileDropZone");
|
|
18
18
|
const fileFieldRef = useRef(null);
|
|
19
19
|
const rootClassName = clsx(FileDropZone_module_default.fileDropZone, isDisabled && FileDropZone_module_default.disabled, className);
|
|
20
20
|
const propsContext = {
|
|
@@ -31,7 +31,8 @@ var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
|
31
31
|
color: "dark"
|
|
32
32
|
},
|
|
33
33
|
isDisabled,
|
|
34
|
-
isReadOnly
|
|
34
|
+
isReadOnly,
|
|
35
|
+
"aria-describedby": controlProps["aria-describedby"]
|
|
35
36
|
},
|
|
36
37
|
Heading: { className: FileDropZone_module_default.heading },
|
|
37
38
|
Icon: { className: FileDropZone_module_default.icon },
|
|
@@ -49,9 +50,10 @@ var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
|
49
50
|
}
|
|
50
51
|
};
|
|
51
52
|
return /* @__PURE__ */ jsxs("div", {
|
|
52
|
-
|
|
53
|
-
children: [/* @__PURE__ */ jsx(
|
|
53
|
+
className: wrapperProps.className,
|
|
54
|
+
children: [/* @__PURE__ */ jsx(PropsContextProvider, {
|
|
54
55
|
props: propsContext,
|
|
56
|
+
dependencies: [controlProps["aria-describedby"]],
|
|
55
57
|
children: /* @__PURE__ */ jsx(Aria.DropZone, {
|
|
56
58
|
className: rootClassName,
|
|
57
59
|
onDrop: onDropHandler,
|
|
@@ -59,10 +61,10 @@ var FileDropZone = flowComponent("FileDropZone", (props) => {
|
|
|
59
61
|
"data-readonly": isReadOnly,
|
|
60
62
|
children: /* @__PURE__ */ jsx(IllustratedMessage, {
|
|
61
63
|
color: "dark",
|
|
62
|
-
children
|
|
64
|
+
children: /* @__PURE__ */ jsx(FieldErrorCaptureContext, { children })
|
|
63
65
|
})
|
|
64
66
|
})
|
|
65
|
-
})
|
|
67
|
+
}), /* @__PURE__ */ jsx(FieldErrorView, {})]
|
|
66
68
|
});
|
|
67
69
|
});
|
|
68
70
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDropZone.mjs","names":[],"sources":["../../../../../../../src/components/FileDropZone/FileDropZone.tsx"],"sourcesContent":["import { type FC, type PropsWithChildren, useRef } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport { IllustratedMessage } from \"@/components/IllustratedMessage\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport styles from \"./FileDropZone.module.scss\";\nimport clsx from \"clsx\";\nimport type { FileInputOnChangeHandler } from \"@/components/FileField/components/FileInput\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport type { DropEvent, FocusableElement } from \"@react-types/shared\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { getAcceptedFiles } from \"@/lib/files/acceptedFiles\";\n\nexport interface FileDropZoneProps\n extends\n PropsWithClassName,\n FlowComponentProps<FocusableElement>,\n PropsWithChildren,\n Pick<Aria.InputProps, \"accept\" | \"multiple\" | \"name\">,\n Pick<Aria.DropZoneProps, \"isDisabled\"> {\n /** Called with the dropped or selected files whenever the selection changes. */\n onChange?: FileInputOnChangeHandler;\n /** Whether the component is read only. */\n isReadOnly?: boolean;\n}\n\n/** @flr-generate all */\nexport const FileDropZone: FC<FileDropZoneProps> = flowComponent(\n \"FileDropZone\",\n (props) => {\n const {\n multiple,\n accept,\n className,\n onChange: onChangeDropZone,\n children,\n name,\n isDisabled,\n isReadOnly,\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n
|
|
1
|
+
{"version":3,"file":"FileDropZone.mjs","names":[],"sources":["../../../../../../../src/components/FileDropZone/FileDropZone.tsx"],"sourcesContent":["import { type FC, type PropsWithChildren, useRef } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport { IllustratedMessage } from \"@/components/IllustratedMessage\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport styles from \"./FileDropZone.module.scss\";\nimport clsx from \"clsx\";\nimport type { FileInputOnChangeHandler } from \"@/components/FileField/components/FileInput\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport type { DropEvent, FocusableElement } from \"@react-types/shared\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { getAcceptedFiles } from \"@/lib/files/acceptedFiles\";\n\nexport interface FileDropZoneProps\n extends\n PropsWithClassName,\n FlowComponentProps<FocusableElement>,\n PropsWithChildren,\n Pick<Aria.InputProps, \"accept\" | \"multiple\" | \"name\">,\n Pick<Aria.DropZoneProps, \"isDisabled\"> {\n /** Called with the dropped or selected files whenever the selection changes. */\n onChange?: FileInputOnChangeHandler;\n /** Whether the component is read only. */\n isReadOnly?: boolean;\n}\n\n/** @flr-generate all */\nexport const FileDropZone: FC<FileDropZoneProps> = flowComponent(\n \"FileDropZone\",\n (props) => {\n const {\n multiple,\n accept,\n className,\n onChange: onChangeDropZone,\n children,\n name,\n isDisabled,\n isReadOnly,\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"FileDropZone\");\n\n const fileFieldRef = useRef<HTMLInputElement>(null);\n const rootClassName = clsx(\n styles.fileDropZone,\n isDisabled && styles.disabled,\n className,\n );\n\n const propsContext: PropsContext = {\n ...fieldPropsContext,\n IllustratedMessage: {\n FileField: {\n name,\n onChange: onChangeDropZone,\n ref: fileFieldRef,\n accept: accept,\n multiple: multiple,\n Button: { variant: \"outline\", color: \"dark\" },\n isDisabled,\n isReadOnly,\n \"aria-describedby\": controlProps[\"aria-describedby\"],\n },\n Heading: {\n className: styles.heading,\n },\n Icon: { className: styles.icon },\n Text: { className: styles.text },\n },\n };\n\n const onDropHandler = async (event: DropEvent) => {\n if (isReadOnly) {\n return;\n }\n\n const files = await getAcceptedFiles(event.items, accept);\n\n if (files.length > 0) {\n const fileTransfer = new DataTransfer();\n for (const file of multiple ? files : [files[0]]) {\n if (file) {\n fileTransfer.items.add(file);\n }\n }\n\n onChangeDropZone?.(fileTransfer.files);\n if (fileFieldRef.current) {\n fileFieldRef.current.files = fileTransfer.files;\n }\n }\n };\n\n return (\n <div className={wrapperProps.className}>\n <PropsContextProvider\n props={propsContext}\n dependencies={[controlProps[\"aria-describedby\"]]}\n >\n <Aria.DropZone\n className={rootClassName}\n onDrop={onDropHandler}\n isDisabled={isDisabled}\n data-readonly={isReadOnly}\n >\n <IllustratedMessage color=\"dark\">\n {/* Inside: IllustratedMessage clears the props context it gets. */}\n <FieldErrorCaptureContext>{children}</FieldErrorCaptureContext>\n </IllustratedMessage>\n </Aria.DropZone>\n </PropsContextProvider>\n <FieldErrorView />\n </div>\n );\n },\n);\n\nexport default FileDropZone;\n"],"mappings":";;;;;;;;;;;;;;AA+BA,IAAa,eAAsC,cACjD,iBACC,UAAU;CACT,MAAM,EACJ,UACA,QACA,WACA,UAAU,kBACV,UACA,MACA,YACA,eACE;CAEJ,MAAM,EACJ,gBACA,0BACA,cACA,cACA,sBACE,kBAAkB,OAAO,cAAc;CAE3C,MAAM,eAAe,OAAyB,IAAI;CAClD,MAAM,gBAAgB,KACpB,4BAAO,cACP,cAAc,4BAAO,UACrB,SACF;CAEA,MAAM,eAA6B;EACjC,GAAG;EACH,oBAAoB;GAClB,WAAW;IACT;IACA,UAAU;IACV,KAAK;IACG;IACE;IACV,QAAQ;KAAE,SAAS;KAAW,OAAO;IAAO;IAC5C;IACA;IACA,oBAAoB,aAAa;GACnC;GACA,SAAS,EACP,WAAW,4BAAO,QACpB;GACA,MAAM,EAAE,WAAW,4BAAO,KAAK;GAC/B,MAAM,EAAE,WAAW,4BAAO,KAAK;EACjC;CACF;CAEA,MAAM,gBAAgB,OAAO,UAAqB;EAChD,IAAI,YACF;EAGF,MAAM,QAAQ,MAAM,iBAAiB,MAAM,OAAO,MAAM;EAExD,IAAI,MAAM,SAAS,GAAG;GACpB,MAAM,eAAe,IAAI,aAAa;GACtC,KAAK,MAAM,QAAQ,WAAW,QAAQ,CAAC,MAAM,EAAE,GAC7C,IAAI,MACF,aAAa,MAAM,IAAI,IAAI;GAI/B,mBAAmB,aAAa,KAAK;GACrC,IAAI,aAAa,SACf,aAAa,QAAQ,QAAQ,aAAa;EAE9C;CACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW,aAAa;EAA7B,UAAA,CACE,oBAAC,sBAAD;GACE,OAAO;GACP,cAAc,CAAC,aAAa,mBAAmB;GAE/C,UAAA,oBAAC,KAAK,UAAN;IACE,WAAW;IACX,QAAQ;IACI;IACZ,iBAAe;IAEf,UAAA,oBAAC,oBAAD;KAAoB,OAAM;KAExB,UAAA,oBAAC,0BAAD,EAA2B,SAAmC,CAAA;IAC5C,CAAA;GACP,CAAA;EACK,CAAA,GACtB,oBAAC,gBAAD,CAAiB,CAAA,CACd;;AAET,CACF"}
|
|
@@ -15,7 +15,7 @@ import { useFormValidationState } from "@react-stately/form";
|
|
|
15
15
|
/** @flr-generate all */
|
|
16
16
|
var FileField = flowComponent("FileField", (props) => {
|
|
17
17
|
const { children, ref, isRequired, isInvalid, isDisabled, validationBehavior, onChange, isReadOnly, ...restInputProps } = props;
|
|
18
|
-
const { FieldErrorView, FieldErrorCaptureContext,
|
|
18
|
+
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext } = useFieldComponent(props, "FileField");
|
|
19
19
|
const inputRef = useObjectRef(ref);
|
|
20
20
|
const formValidationState = useFormValidationState({
|
|
21
21
|
value: void 0,
|
|
@@ -25,6 +25,7 @@ var FileField = flowComponent("FileField", (props) => {
|
|
|
25
25
|
useFormValidation({ validationBehavior }, formValidationState, inputRef);
|
|
26
26
|
const inputProps = {
|
|
27
27
|
...restInputProps,
|
|
28
|
+
"aria-describedby": controlProps["aria-describedby"],
|
|
28
29
|
"aria-invalid": formValidationState.displayValidation.isInvalid,
|
|
29
30
|
value: void 0
|
|
30
31
|
};
|
|
@@ -32,8 +33,7 @@ var FileField = flowComponent("FileField", (props) => {
|
|
|
32
33
|
if (fileList && onChange) onChange(fileList);
|
|
33
34
|
};
|
|
34
35
|
return /* @__PURE__ */ jsx("div", {
|
|
35
|
-
|
|
36
|
-
className: clsx(fieldProps.className, FileField_module_default.fileField),
|
|
36
|
+
className: clsx(wrapperProps.className, FileField_module_default.fileField),
|
|
37
37
|
children: /* @__PURE__ */ jsxs(FieldErrorContext.Provider, {
|
|
38
38
|
value: formValidationState.displayValidation,
|
|
39
39
|
children: [/* @__PURE__ */ jsx(FieldErrorCaptureContext, { children: /* @__PURE__ */ jsx(PropsContextProvider, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileField.mjs","names":[],"sources":["../../../../../../../src/components/FileField/FileField.tsx"],"sourcesContent":["import { useFormValidation } from \"@react-aria/form\";\nimport { useFormValidationState } from \"@react-stately/form\";\nimport type { PropsWithChildren } from \"react\";\nimport type * as Aria from \"react-aria-components\";\nimport { FieldErrorContext } from \"react-aria-components\";\nimport type { FileInputOnChangeHandler } from \"@/components/FileField/components/FileInput\";\nimport { FileInput } from \"@/components/FileField/components/FileInput\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport styles from \"./FileField.module.scss\";\nimport clsx from \"clsx\";\n\nexport interface FileFieldProps\n extends\n PropsWithChildren,\n FlowComponentProps<HTMLInputElement>,\n Pick<Aria.InputProps, \"accept\" | \"multiple\" | \"name\">,\n Pick<\n Aria.TextFieldProps,\n \"isRequired\" | \"isInvalid\" | \"validationBehavior\" | \"isDisabled\"\n > {\n /** Handler that is called when the file input changes. */\n onChange?: FileInputOnChangeHandler;\n /** Whether the component is read only. */\n isReadOnly?: boolean;\n}\n\n/** @flr-generate all */\nexport const FileField = flowComponent(\"FileField\", (props) => {\n const {\n children,\n ref,\n isRequired,\n isInvalid,\n isDisabled,\n validationBehavior,\n onChange,\n isReadOnly,\n ...restInputProps\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n
|
|
1
|
+
{"version":3,"file":"FileField.mjs","names":[],"sources":["../../../../../../../src/components/FileField/FileField.tsx"],"sourcesContent":["import { useFormValidation } from \"@react-aria/form\";\nimport { useFormValidationState } from \"@react-stately/form\";\nimport type { PropsWithChildren } from \"react\";\nimport type * as Aria from \"react-aria-components\";\nimport { FieldErrorContext } from \"react-aria-components\";\nimport type { FileInputOnChangeHandler } from \"@/components/FileField/components/FileInput\";\nimport { FileInput } from \"@/components/FileField/components/FileInput\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport styles from \"./FileField.module.scss\";\nimport clsx from \"clsx\";\n\nexport interface FileFieldProps\n extends\n PropsWithChildren,\n FlowComponentProps<HTMLInputElement>,\n Pick<Aria.InputProps, \"accept\" | \"multiple\" | \"name\" | \"aria-describedby\">,\n Pick<\n Aria.TextFieldProps,\n \"isRequired\" | \"isInvalid\" | \"validationBehavior\" | \"isDisabled\"\n > {\n /** Handler that is called when the file input changes. */\n onChange?: FileInputOnChangeHandler;\n /** Whether the component is read only. */\n isReadOnly?: boolean;\n}\n\n/** @flr-generate all */\nexport const FileField = flowComponent(\"FileField\", (props) => {\n const {\n children,\n ref,\n isRequired,\n isInvalid,\n isDisabled,\n validationBehavior,\n onChange,\n isReadOnly,\n ...restInputProps\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"FileField\");\n\n const inputRef = useObjectRef(ref);\n\n const formValidationState = useFormValidationState({\n value: undefined,\n validationBehavior,\n isInvalid,\n });\n\n useFormValidation({ validationBehavior }, formValidationState, inputRef);\n\n const inputProps = {\n ...restInputProps,\n \"aria-describedby\": controlProps[\"aria-describedby\"],\n \"aria-invalid\": formValidationState.displayValidation.isInvalid,\n value: undefined,\n };\n\n const handleChange: FileInputOnChangeHandler = (fileList) => {\n if (fileList && onChange) {\n onChange(fileList);\n }\n };\n\n return (\n <div className={clsx(wrapperProps.className, styles.fileField)}>\n <FieldErrorContext.Provider value={formValidationState.displayValidation}>\n <FieldErrorCaptureContext>\n <PropsContextProvider props={fieldPropsContext}>\n <div\n data-readonly={isReadOnly}\n data-required={!!isRequired || undefined}\n data-invalid={\n formValidationState.displayValidation.isInvalid || undefined\n }\n >\n <FileInput\n ref={inputRef}\n isReadOnly={isReadOnly}\n onChange={isReadOnly ? undefined : handleChange}\n isDisabled={isDisabled}\n {...inputProps}\n >\n {children}\n </FileInput>\n </div>\n </PropsContextProvider>\n </FieldErrorCaptureContext>\n <FieldErrorView />\n </FieldErrorContext.Provider>\n </div>\n );\n});\nexport default FileField;\n"],"mappings":";;;;;;;;;;;;;;;AA+BA,IAAa,YAAY,cAAc,cAAc,UAAU;CAC7D,MAAM,EACJ,UACA,KACA,YACA,WACA,YACA,oBACA,UACA,YACA,GAAG,mBACD;CAEJ,MAAM,EACJ,gBACA,0BACA,cACA,cACA,sBACE,kBAAkB,OAAO,WAAW;CAExC,MAAM,WAAW,aAAa,GAAG;CAEjC,MAAM,sBAAsB,uBAAuB;EACjD,OAAO,KAAA;EACP;EACA;CACF,CAAC;CAED,kBAAkB,EAAE,mBAAmB,GAAG,qBAAqB,QAAQ;CAEvE,MAAM,aAAa;EACjB,GAAG;EACH,oBAAoB,aAAa;EACjC,gBAAgB,oBAAoB,kBAAkB;EACtD,OAAO,KAAA;CACT;CAEA,MAAM,gBAA0C,aAAa;EAC3D,IAAI,YAAY,UACd,SAAS,QAAQ;CAErB;CAEA,OACE,oBAAC,OAAD;EAAK,WAAW,KAAK,aAAa,WAAW,yBAAO,SAAS;EAC3D,UAAA,qBAAC,kBAAkB,UAAnB;GAA4B,OAAO,oBAAoB;GAAvD,UAAA,CACE,oBAAC,0BAAD,EAAA,UACE,oBAAC,sBAAD;IAAsB,OAAO;IAC3B,UAAA,oBAAC,OAAD;KACE,iBAAe;KACf,iBAAe,CAAC,CAAC,cAAc,KAAA;KAC/B,gBACE,oBAAoB,kBAAkB,aAAa,KAAA;KAGrD,UAAA,oBAAC,WAAD;MACE,KAAK;MACO;MACZ,UAAU,aAAa,KAAA,IAAY;MACvB;MACZ,GAAI;MAEH;KACQ,CAAA;IACR,CAAA;GACe,CAAA,EACE,CAAA,GAC1B,oBAAC,gBAAD,CAAiB,CAAA,CACS;;CACzB,CAAA;AAET,CAAC"}
|
|
@@ -19,12 +19,13 @@ import * as Aria from "react-aria-components";
|
|
|
19
19
|
/** @flr-generate all */
|
|
20
20
|
var NumberField = flowComponent("NumberField", (props) => {
|
|
21
21
|
const { children, className, isWheelDisabled = true, ref, ...rest } = useControlledHostValueProps(props, NaN);
|
|
22
|
-
const { FieldErrorView, FieldErrorCaptureContext,
|
|
22
|
+
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext } = useFieldComponent(props, "NumberField");
|
|
23
23
|
const rootClassName = clsx(FormField_module_default.formField, className);
|
|
24
24
|
return /* @__PURE__ */ jsxs(Aria.NumberField, {
|
|
25
25
|
...rest,
|
|
26
26
|
isWheelDisabled,
|
|
27
|
-
|
|
27
|
+
"aria-describedby": controlProps["aria-describedby"],
|
|
28
|
+
className: clsx(rootClassName, wrapperProps.className),
|
|
28
29
|
children: [/* @__PURE__ */ jsxs(PropsContextProvider, {
|
|
29
30
|
props: fieldPropsContext,
|
|
30
31
|
children: [/* @__PURE__ */ jsx(FieldErrorCaptureContext, { children }), /* @__PURE__ */ jsx(FieldErrorView, {})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberField.mjs","names":[],"sources":["../../../../../../../src/components/NumberField/NumberField.tsx"],"sourcesContent":["import { type PropsWithChildren } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport formFieldStyles from \"@/components/FormField/FormField.module.scss\";\nimport styles from \"./NumberField.module.scss\";\nimport clsx from \"clsx\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport { Button } from \"@/components/Button\";\nimport {\n IconChevronDown,\n IconChevronUp,\n IconMinus,\n IconPlus,\n} from \"@/components/Icon/components/icons\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { useControlledHostValueProps } from \"@/lib/remote/useControlledHostValueProps\";\n\nexport interface NumberFieldProps\n extends\n PropsWithChildren<Omit<Aria.NumberFieldProps, \"children\">>,\n FlowComponentProps<HTMLInputElement> {}\n\n/** @flr-generate all */\nexport const NumberField = flowComponent(\"NumberField\", (props) => {\n // `NaN` is what react-aria's number field state uses for \"no number\"\n const {\n children,\n className,\n isWheelDisabled = true,\n ref,\n ...rest\n } = useControlledHostValueProps(props, NaN);\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n
|
|
1
|
+
{"version":3,"file":"NumberField.mjs","names":[],"sources":["../../../../../../../src/components/NumberField/NumberField.tsx"],"sourcesContent":["import { type PropsWithChildren } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport formFieldStyles from \"@/components/FormField/FormField.module.scss\";\nimport styles from \"./NumberField.module.scss\";\nimport clsx from \"clsx\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport { Button } from \"@/components/Button\";\nimport {\n IconChevronDown,\n IconChevronUp,\n IconMinus,\n IconPlus,\n} from \"@/components/Icon/components/icons\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { useControlledHostValueProps } from \"@/lib/remote/useControlledHostValueProps\";\n\nexport interface NumberFieldProps\n extends\n PropsWithChildren<Omit<Aria.NumberFieldProps, \"children\">>,\n FlowComponentProps<HTMLInputElement> {}\n\n/** @flr-generate all */\nexport const NumberField = flowComponent(\"NumberField\", (props) => {\n // `NaN` is what react-aria's number field state uses for \"no number\"\n const {\n children,\n className,\n isWheelDisabled = true,\n ref,\n ...rest\n } = useControlledHostValueProps(props, NaN);\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"NumberField\");\n\n const rootClassName = clsx(formFieldStyles.formField, className);\n\n return (\n <Aria.NumberField\n {...rest}\n isWheelDisabled={isWheelDisabled}\n aria-describedby={controlProps[\"aria-describedby\"]}\n className={clsx(rootClassName, wrapperProps.className)}\n >\n <PropsContextProvider props={fieldPropsContext}>\n <FieldErrorCaptureContext>{children}</FieldErrorCaptureContext>\n <FieldErrorView />\n </PropsContextProvider>\n <Aria.Group className={styles.group}>\n <Button\n ariaSlot=\"decrement\"\n className={styles.decrementButton}\n size=\"s\"\n variant=\"plain\"\n color=\"secondary\"\n >\n <IconChevronDown />\n <IconMinus className={styles.coarsePointerIcon} />\n </Button>\n <Aria.Input className={styles.input} ref={ref} />\n <Button\n ariaSlot=\"increment\"\n className={styles.incrementButton}\n size=\"s\"\n variant=\"plain\"\n color=\"secondary\"\n >\n <IconChevronUp />\n <IconPlus className={styles.coarsePointerIcon} />\n </Button>\n </Aria.Group>\n </Aria.NumberField>\n );\n});\n\nexport default NumberField;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwBA,IAAa,cAAc,cAAc,gBAAgB,UAAU;CAEjE,MAAM,EACJ,UACA,WACA,kBAAkB,MAClB,KACA,GAAG,SACD,4BAA4B,OAAO,GAAG;CAE1C,MAAM,EACJ,gBACA,0BACA,cACA,cACA,sBACE,kBAAkB,OAAO,aAAa;CAE1C,MAAM,gBAAgB,KAAK,yBAAgB,WAAW,SAAS;CAE/D,OACE,qBAAC,KAAK,aAAN;EACE,GAAI;EACa;EACjB,oBAAkB,aAAa;EAC/B,WAAW,KAAK,eAAe,aAAa,SAAS;EAJvD,UAAA,CAME,qBAAC,sBAAD;GAAsB,OAAO;GAA7B,UAAA,CACE,oBAAC,0BAAD,EAA2B,SAAmC,CAAA,GAC9D,oBAAC,gBAAD,CAAiB,CAAA,CACG;EACtB,CAAA,GAAA,qBAAC,KAAK,OAAN;GAAY,WAAW,2BAAO;GAA9B,UAAA;IACE,qBAAC,QAAD;KACE,UAAS;KACT,WAAW,2BAAO;KAClB,MAAK;KACL,SAAQ;KACR,OAAM;KALR,UAAA,CAOE,oBAAC,iBAAD,CAAkB,CAAA,GAClB,oBAAC,WAAD,EAAW,WAAW,2BAAO,kBAAoB,CAAA,CAC3C;;IACR,oBAAC,KAAK,OAAN;KAAY,WAAW,2BAAO;KAAY;IAAM,CAAA;IAChD,qBAAC,QAAD;KACE,UAAS;KACT,WAAW,2BAAO;KAClB,MAAK;KACL,SAAQ;KACR,OAAM;KALR,UAAA,CAOE,oBAAC,eAAD,CAAgB,CAAA,GAChB,oBAAC,UAAD,EAAU,WAAW,2BAAO,kBAAoB,CAAA,CAC1C;;GACE;EACI,CAAA,CAAA;;AAEtB,CAAC"}
|
package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { flowComponent } from "../../lib/componentFactory/flowComponent.mjs";
|
|
|
5
5
|
import dynamic from "../../lib/propsContext/dynamicProps/dynamic.mjs";
|
|
6
6
|
import { useLocalizedStringFormatter } from "../TranslationProvider/useLocalizedStringFormatter.mjs";
|
|
7
7
|
import { UiComponentTunnelExit } from "../UiComponentTunnel/UiComponentTunnelExit.mjs";
|
|
8
|
-
import { useFieldComponent } from "../../lib/hooks/useFieldComponent.mjs";
|
|
8
|
+
import { joinIds, useFieldComponent } from "../../lib/hooks/useFieldComponent.mjs";
|
|
9
9
|
import { useControlledHostValueProps } from "../../lib/remote/useControlledHostValueProps.mjs";
|
|
10
10
|
import { FieldDescription } from "../FieldDescription/FieldDescription.mjs";
|
|
11
11
|
import { FieldError } from "../FieldError/FieldError.mjs";
|
|
@@ -23,7 +23,7 @@ import { PasswordGenerateButton } from "./components/PasswordGenerateButton/Pass
|
|
|
23
23
|
import { usePolicyValidationResult } from "./lib/usePolicyValidationResult.mjs";
|
|
24
24
|
import { useAriaAnnouncePasswordVisibility, useAriaAnnounceValidationState } from "./lib/ariaAnnounce.mjs";
|
|
25
25
|
import clsx from "clsx";
|
|
26
|
-
import { useMemo, useRef, useState } from "react";
|
|
26
|
+
import { useCallback, useId, useMemo, useRef, useState } from "react";
|
|
27
27
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
28
28
|
import * as Aria from "react-aria-components";
|
|
29
29
|
//#region src/components/PasswordCreationField/PasswordCreationField.tsx
|
|
@@ -44,7 +44,7 @@ var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
|
44
44
|
};
|
|
45
45
|
const [policyValidationResult, setPolicyValidationResult] = useState(initialPolicyValidationState);
|
|
46
46
|
const loadingRef = useRef(null);
|
|
47
|
-
usePolicyValidationResult(validationPolicy, value ?? "", () => {
|
|
47
|
+
const { rememberValidationResult } = usePolicyValidationResult(validationPolicy, value ?? "", () => {
|
|
48
48
|
if (isEmptyValue) return;
|
|
49
49
|
loadingRef.current = setTimeout(() => {
|
|
50
50
|
setPolicyValidationResult((r) => ({
|
|
@@ -77,10 +77,23 @@ var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
|
77
77
|
const isValidFromValidationResult = !isEmptyValue && stateFromValidationResult?.isValid;
|
|
78
78
|
const isInvalidFromValidationResult = !isEmptyValue && stateFromValidationResult?.isValid === false;
|
|
79
79
|
const isInvalid = invalidFromProps || isInvalidFromValidationResult;
|
|
80
|
-
const { FieldErrorView, FieldErrorCaptureContext,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext, renderedFieldErrorId } = useFieldComponent(props, "PasswordCreationField");
|
|
81
|
+
/**
|
|
82
|
+
* The result for a valid password appears after the asynchronous policy
|
|
83
|
+
* validation. react-aria resolves its description slot only when the
|
|
84
|
+
* field's validity changes, so a result that appears while the field stays
|
|
85
|
+
* valid (a generated password) was never linked. It gets its own id
|
|
86
|
+
* instead, referenced only while it is rendered.
|
|
87
|
+
*
|
|
88
|
+
* A shown error replaces it: the FormField styles hide descriptions next to
|
|
89
|
+
* an error, and a hidden description would still be announced.
|
|
90
|
+
*/
|
|
91
|
+
const resultDescriptionId = useId();
|
|
92
|
+
const [isResultDescriptionRendered, setIsResultDescriptionRendered] = useState(false);
|
|
93
|
+
const resultDescriptionRef = useCallback((element) => {
|
|
94
|
+
setIsResultDescriptionRendered(!!element);
|
|
95
|
+
}, []);
|
|
96
|
+
const describedBy = joinIds(isResultDescriptionRendered && resultDescriptionId, controlProps["aria-describedby"]);
|
|
84
97
|
useAriaAnnounceValidationState(latestValidationErrorText, !isEmptyValue && policyValidationResult.isValid !== "indeterminate");
|
|
85
98
|
useAriaAnnouncePasswordVisibility(isPasswordRevealed);
|
|
86
99
|
const setOptimisticPolicyValidationResult = (state = {}) => {
|
|
@@ -92,14 +105,16 @@ var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
|
92
105
|
};
|
|
93
106
|
const onPasswordGenerateHandler = async () => {
|
|
94
107
|
const generatedPassword = await generatePassword(validationPolicy);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
/**
|
|
109
|
+
* The generator returns only passwords the policy accepts, so the rating
|
|
110
|
+
* is set with the password instead of after the typing debounce. It is
|
|
111
|
+
* the policy's own result: a guessed one (full strength) was overturned
|
|
112
|
+
* by the real rating, e.g. to "meets the minimum requirements". Cached,
|
|
113
|
+
* so the debounced validation of this password does not rate it again.
|
|
114
|
+
*/
|
|
115
|
+
const generatedPasswordResult = await validationPolicy.validate(generatedPassword);
|
|
116
|
+
rememberValidationResult(generatedPassword, generatedPasswordResult);
|
|
117
|
+
setPolicyValidationResult(generatedPasswordResult);
|
|
103
118
|
setIsPasswordRevealed(true);
|
|
104
119
|
onChange(generatedPassword);
|
|
105
120
|
};
|
|
@@ -155,12 +170,12 @@ var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
|
155
170
|
};
|
|
156
171
|
return /* @__PURE__ */ jsxs(Aria.TextField, {
|
|
157
172
|
...rest,
|
|
158
|
-
|
|
173
|
+
"aria-describedby": describedBy,
|
|
159
174
|
value,
|
|
160
175
|
type: isPasswordRevealed ? "text" : "password",
|
|
161
176
|
onChange,
|
|
162
177
|
onPaste: onPasswordPasteHandler,
|
|
163
|
-
className: clsx(className,
|
|
178
|
+
className: clsx(className, wrapperProps.className),
|
|
164
179
|
isDisabled,
|
|
165
180
|
isInvalid,
|
|
166
181
|
isRequired,
|
|
@@ -199,11 +214,19 @@ var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
|
199
214
|
isEmptyValue,
|
|
200
215
|
isLoading: policyValidationResult.isValid === "indeterminate",
|
|
201
216
|
policyValidationResult,
|
|
202
|
-
validationResultState: stateFromValidationResult
|
|
217
|
+
validationResultState: stateFromValidationResult,
|
|
218
|
+
isInvalid: invalidFromProps
|
|
203
219
|
}, value)
|
|
204
220
|
]
|
|
205
221
|
}),
|
|
206
|
-
isValidFromValidationResult && /* @__PURE__ */ jsx(
|
|
222
|
+
isValidFromValidationResult && !renderedFieldErrorId && /* @__PURE__ */ jsx(Aria.TextContext.Provider, {
|
|
223
|
+
value: null,
|
|
224
|
+
children: /* @__PURE__ */ jsx(FieldDescription, {
|
|
225
|
+
id: resultDescriptionId,
|
|
226
|
+
ref: resultDescriptionRef,
|
|
227
|
+
children: latestValidationErrorText
|
|
228
|
+
})
|
|
229
|
+
})
|
|
207
230
|
]
|
|
208
231
|
})] }), /* @__PURE__ */ jsx(FieldErrorView, {})]
|
|
209
232
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordCreationField.mjs","names":[],"sources":["../../../../../../../src/components/PasswordCreationField/PasswordCreationField.tsx"],"sourcesContent":["import {\n type PropsWithChildren,\n useState,\n type ClipboardEvent,\n useMemo,\n useRef,\n} from \"react\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport styles from \"./PasswordCreationField.module.scss\";\nimport * as Aria from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport { type ActionFn } from \"@/components/Action\";\nimport getStateFromLatestPolicyValidationResult from \"@/components/PasswordCreationField/lib/getStateFromLatestPolicyValidationResult\";\nimport locales from \"./locales/*.locale.json\";\nimport generateValidationTranslation from \"@/components/PasswordCreationField/lib/generateValidationTranslation\";\nimport FieldDescription from \"@/components/FieldDescription\";\nimport ComplexityIndicator from \"@/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator\";\nimport { generatePassword } from \"@/components/PasswordCreationField/worker/generatePassword\";\nimport TogglePasswordVisibilityButton from \"@/components/PasswordCreationField/components/TogglePasswordVisibilityButton/TogglePasswordVisibilityButton\";\nimport { ValidationResultButton } from \"@/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton\";\nimport { PasswordGenerateButton } from \"@/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton\";\nimport type {\n PolicyValidationResult,\n PolicyGenericDeclaration,\n RuleValidationResult,\n} from \"@/integrations/@mittwald/password-tools-js\";\nimport {\n defaultPasswordCreationPolicy,\n Policy,\n} from \"@/integrations/@mittwald/password-tools-js\";\nimport { usePolicyValidationResult } from \"@/components/PasswordCreationField/lib/usePolicyValidationResult\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { FieldError } from \"@/components/FieldError\";\nimport { useControlledHostValueProps } from \"@/lib/remote/useControlledHostValueProps\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\nimport {\n useAriaAnnouncePasswordVisibility,\n useAriaAnnounceValidationState,\n} from \"@/components/PasswordCreationField/lib/ariaAnnounce\";\n\nexport interface PasswordCreationFieldProps\n extends\n PropsWithChildren<\n Omit<Aria.TextFieldProps, \"children\" | \"value\" | \"defaultValue\"> &\n Partial<Pick<Aria.FieldErrorRenderProps, \"validationErrors\">>\n >,\n FlowComponentProps<HTMLInputElement> {\n /** The password of a controlled field. */\n value?: string;\n /** Called with the password and its validity whenever the password changes. */\n onValidationResult?: (result: { password: string; isValid: boolean }) => void;\n /** The initial password of an uncontrolled field. */\n defaultValue?: string;\n /** The placeholder shown while the field is empty. */\n placeholder?: string;\n /**\n * The policy the password is validated against.\n *\n * @default defaultPasswordCreationPolicy\n */\n validationPolicy?: PolicyGenericDeclaration;\n}\n\nexport interface ResolvedPolicyValidationResult extends Omit<\n PolicyValidationResult,\n \"isValid\"\n> {\n isValid: boolean | \"indeterminate\";\n ruleResults: RuleValidationResult[];\n}\n\n/** @flr-generate all */\nexport const PasswordCreationField = flowComponent(\n \"PasswordCreationField\",\n (props) => {\n const {\n children,\n className,\n ref,\n isDisabled,\n onValidationResult,\n isInvalid: invalidFromProps,\n validationPolicy:\n validationPolicyFromProps = defaultPasswordCreationPolicy,\n isRequired,\n value,\n onChange,\n ...rest\n } = useControlledHostValueProps(props, \"\");\n\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n const validationPolicy = useMemo(\n () => Policy.fromDeclaration(validationPolicyFromProps),\n [validationPolicyFromProps],\n );\n\n const [isPasswordRevealed, setIsPasswordRevealed] = useState(false);\n const initialPolicyValidationState: ResolvedPolicyValidationResult = {\n isValid: \"indeterminate\",\n complexity: {\n min: validationPolicy.minComplexity,\n actual: 4,\n warning: null,\n },\n ruleResults: [],\n };\n\n const [policyValidationResult, setPolicyValidationResult] = useState(\n initialPolicyValidationState,\n );\n\n const loadingRef = useRef<ReturnType<typeof setTimeout>>(null);\n usePolicyValidationResult(\n validationPolicy,\n value ?? \"\",\n () => {\n if (isEmptyValue) {\n return;\n }\n\n loadingRef.current = setTimeout(() => {\n setPolicyValidationResult((r) => ({\n ...r,\n isValid: \"indeterminate\",\n }));\n }, 150);\n },\n ({ password, isValid, results }) => {\n if (loadingRef.current) {\n clearTimeout(loadingRef.current);\n }\n\n if (isEmptyValue) {\n setPolicyValidationResult(() => ({\n ...results,\n isValid: true,\n }));\n return;\n }\n\n setPolicyValidationResult(() => results);\n onValidationResult?.({ password, isValid });\n },\n );\n\n const isEmptyValue = !value;\n const stateFromValidationResult = getStateFromLatestPolicyValidationResult(\n isEmptyValue,\n policyValidationResult,\n );\n let latestValidationErrorText = undefined;\n if (stateFromValidationResult) {\n const [translationKey, translationValues] = generateValidationTranslation(\n stateFromValidationResult,\n );\n latestValidationErrorText = translate.format(\n translationKey,\n translationValues,\n );\n }\n\n const isValidFromValidationResult =\n !isEmptyValue && stateFromValidationResult?.isValid;\n\n const isInvalidFromValidationResult =\n !isEmptyValue && stateFromValidationResult?.isValid === false;\n const isInvalid = invalidFromProps || isInvalidFromValidationResult;\n\n // The field derives its invalid state from the policy validation, so the\n // hook has to see that state — not just the `isInvalid` prop — to describe\n // the input with the field error.\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n fieldProps,\n fieldPropsContext,\n } = useFieldComponent({ ...props, isInvalid }, \"PasswordCreationField\");\n\n useAriaAnnounceValidationState(\n latestValidationErrorText,\n !isEmptyValue && policyValidationResult.isValid !== \"indeterminate\",\n );\n useAriaAnnouncePasswordVisibility(isPasswordRevealed);\n\n const setOptimisticPolicyValidationResult = (\n state: Partial<ResolvedPolicyValidationResult> = {},\n ) => {\n setPolicyValidationResult((currentState) => ({\n ...currentState,\n isValid: true,\n ...state,\n }));\n };\n\n const onPasswordGenerateHandler: ActionFn = async () => {\n const generatedPassword = await generatePassword(validationPolicy);\n setOptimisticPolicyValidationResult({\n ...initialPolicyValidationState,\n isValid: true,\n ruleResults: policyValidationResult.ruleResults.map((r) => ({\n ...r,\n isValid: true,\n })),\n });\n setIsPasswordRevealed(true);\n onChange(generatedPassword);\n };\n\n const onPasswordPasteHandler = (event: ClipboardEvent) => {\n const pastedValue = event.clipboardData?.getData(\"text\");\n if (typeof pastedValue === \"string\" && pastedValue !== value) {\n setOptimisticPolicyValidationResult({\n isValid: \"indeterminate\",\n });\n }\n };\n\n const togglePasswordVisibilityHandler = () => {\n setIsPasswordRevealed((old) => !old);\n };\n\n const propsContext: PropsContext = {\n ...fieldPropsContext,\n Button: {\n tunnel: {\n id: \"button\",\n component: \"PasswordCreationField\",\n },\n size: \"m\",\n variant: \"plain\",\n color: \"secondary\",\n isDisabled: isDisabled,\n className: styles.button,\n },\n CopyButton: {\n tunnel: {\n id: \"button\",\n component: \"PasswordCreationField\",\n },\n size: \"m\",\n variant: \"plain\",\n color: \"secondary\",\n isDisabled: isDisabled,\n className: styles.button,\n text: value,\n },\n Label: {\n ...fieldPropsContext.Label,\n children: dynamic((localProps) => {\n return (\n <>\n {localProps.children}\n <PasswordGenerateButton\n isDisabled={isDisabled}\n onGeneratePasswordAction={onPasswordGenerateHandler}\n />\n <ValidationResultButton\n isEmptyValue={isEmptyValue}\n isDisabled={isDisabled}\n policyValidationResult={policyValidationResult}\n />\n </>\n );\n }),\n },\n };\n\n return (\n <Aria.TextField\n {...rest}\n {...fieldProps}\n value={value}\n type={isPasswordRevealed ? \"text\" : \"password\"}\n onChange={onChange}\n onPaste={onPasswordPasteHandler}\n className={clsx(className, fieldProps.className)}\n isDisabled={isDisabled}\n isInvalid={isInvalid}\n isRequired={isRequired}\n >\n <FieldErrorCaptureContext>\n {latestValidationErrorText && (\n <FieldError>{latestValidationErrorText}</FieldError>\n )}\n <PropsContextProvider\n props={propsContext}\n dependencies={[\n isDisabled,\n isRequired,\n value,\n policyValidationResult,\n isEmptyValue,\n ]}\n >\n {children}\n <Aria.Group\n isDisabled={isDisabled}\n className={clsx(styles.inputGroup)}\n >\n <Aria.Input ref={ref} className={styles.input} />\n <Aria.Group className={styles.buttonContainer}>\n <TogglePasswordVisibilityButton\n className={styles.button}\n isVisible={isPasswordRevealed}\n isDisabled={isDisabled}\n onPress={togglePasswordVisibilityHandler}\n />\n <UiComponentTunnelExit\n id=\"button\"\n component=\"PasswordCreationField\"\n />\n </Aria.Group>\n <ComplexityIndicator\n key={value}\n isEmptyValue={isEmptyValue}\n isLoading={policyValidationResult.isValid === \"indeterminate\"}\n policyValidationResult={policyValidationResult}\n validationResultState={stateFromValidationResult}\n />\n </Aria.Group>\n {isValidFromValidationResult && (\n <FieldDescription>{latestValidationErrorText}</FieldDescription>\n )}\n </PropsContextProvider>\n </FieldErrorCaptureContext>\n <FieldErrorView />\n </Aria.TextField>\n );\n },\n);\n\nexport default PasswordCreationField;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFA,IAAa,wBAAwB,cACnC,0BACC,UAAU;CACT,MAAM,EACJ,UACA,WACA,KACA,YACA,oBACA,WAAW,kBACX,kBACE,4BAA4B,+BAC9B,YACA,OACA,UACA,GAAG,SACD,4BAA4B,OAAO,EAAE;CAEzC,MAAM,YAAY,4BAChB,kBACA,uBACF;CAEA,MAAM,mBAAmB,cACjB,OAAO,gBAAgB,yBAAyB,GACtD,CAAC,yBAAyB,CAC5B;CAEA,MAAM,CAAC,oBAAoB,yBAAyB,SAAS,KAAK;CAClE,MAAM,+BAA+D;EACnE,SAAS;EACT,YAAY;GACV,KAAK,iBAAiB;GACtB,QAAQ;GACR,SAAS;EACX;EACA,aAAa,CAAC;CAChB;CAEA,MAAM,CAAC,wBAAwB,6BAA6B,SAC1D,4BACF;CAEA,MAAM,aAAa,OAAsC,IAAI;CAC7D,0BACE,kBACA,SAAS,UACH;EACJ,IAAI,cACF;EAGF,WAAW,UAAU,iBAAiB;GACpC,2BAA2B,OAAO;IAChC,GAAG;IACH,SAAS;GACX,EAAE;EACJ,GAAG,GAAG;CACR,IACC,EAAE,UAAU,SAAS,cAAc;EAClC,IAAI,WAAW,SACb,aAAa,WAAW,OAAO;EAGjC,IAAI,cAAc;GAChB,iCAAiC;IAC/B,GAAG;IACH,SAAS;GACX,EAAE;GACF;EACF;EAEA,gCAAgC,OAAO;EACvC,qBAAqB;GAAE;GAAU;EAAQ,CAAC;CAC5C,CACF;CAEA,MAAM,eAAe,CAAC;CACtB,MAAM,4BAA4B,yCAChC,cACA,sBACF;CACA,IAAI,4BAA4B,KAAA;CAChC,IAAI,2BAA2B;EAC7B,MAAM,CAAC,gBAAgB,qBAAqB,8BAC1C,yBACF;EACA,4BAA4B,UAAU,OACpC,gBACA,iBACF;CACF;CAEA,MAAM,8BACJ,CAAC,gBAAgB,2BAA2B;CAE9C,MAAM,gCACJ,CAAC,gBAAgB,2BAA2B,YAAY;CAC1D,MAAM,YAAY,oBAAoB;CAKtC,MAAM,EACJ,gBACA,0BACA,YACA,sBACE,kBAAkB;EAAE,GAAG;EAAO;CAAU,GAAG,uBAAuB;CAEtE,+BACE,2BACA,CAAC,gBAAgB,uBAAuB,YAAY,eACtD;CACA,kCAAkC,kBAAkB;CAEpD,MAAM,uCACJ,QAAiD,CAAC,MAC/C;EACH,2BAA2B,kBAAkB;GAC3C,GAAG;GACH,SAAS;GACT,GAAG;EACL,EAAE;CACJ;CAEA,MAAM,4BAAsC,YAAY;EACtD,MAAM,oBAAoB,MAAM,iBAAiB,gBAAgB;EACjE,oCAAoC;GAClC,GAAG;GACH,SAAS;GACT,aAAa,uBAAuB,YAAY,KAAK,OAAO;IAC1D,GAAG;IACH,SAAS;GACX,EAAE;EACJ,CAAC;EACD,sBAAsB,IAAI;EAC1B,SAAS,iBAAiB;CAC5B;CAEA,MAAM,0BAA0B,UAA0B;EACxD,MAAM,cAAc,MAAM,eAAe,QAAQ,MAAM;EACvD,IAAI,OAAO,gBAAgB,YAAY,gBAAgB,OACrD,oCAAoC,EAClC,SAAS,gBACX,CAAC;CAEL;CAEA,MAAM,wCAAwC;EAC5C,uBAAuB,QAAQ,CAAC,GAAG;CACrC;CAEA,MAAM,eAA6B;EACjC,GAAG;EACH,QAAQ;GACN,QAAQ;IACN,IAAI;IACJ,WAAW;GACb;GACA,MAAM;GACN,SAAS;GACT,OAAO;GACK;GACZ,WAAW,qCAAO;EACpB;EACA,YAAY;GACV,QAAQ;IACN,IAAI;IACJ,WAAW;GACb;GACA,MAAM;GACN,SAAS;GACT,OAAO;GACK;GACZ,WAAW,qCAAO;GAClB,MAAM;EACR;EACA,OAAO;GACL,GAAG,kBAAkB;GACrB,UAAU,SAAS,eAAe;IAChC,OACE,qBAAA,YAAA,EAAA,UAAA;KACG,WAAW;KACZ,oBAAC,wBAAD;MACc;MACZ,0BAA0B;KAC3B,CAAA;KACD,oBAAC,wBAAD;MACgB;MACF;MACY;KACzB,CAAA;IACD,EAAA,CAAA;GAEN,CAAC;EACH;CACF;CAEA,OACE,qBAAC,KAAK,WAAN;EACE,GAAI;EACJ,GAAI;EACG;EACP,MAAM,qBAAqB,SAAS;EAC1B;EACV,SAAS;EACT,WAAW,KAAK,WAAW,WAAW,SAAS;EACnC;EACD;EACC;EAVd,UAAA,CAYE,qBAAC,0BAAD,EAAA,UAAA,CACG,6BACC,oBAAC,YAAD,EAAA,UAAa,0BAAsC,CAAA,GAErD,qBAAC,sBAAD;GACE,OAAO;GACP,cAAc;IACZ;IACA;IACA;IACA;IACA;GACF;GARF,UAAA;IAUG;IACD,qBAAC,KAAK,OAAN;KACc;KACZ,WAAW,KAAK,qCAAO,UAAU;KAFnC,UAAA;MAIE,oBAAC,KAAK,OAAN;OAAiB;OAAK,WAAW,qCAAO;MAAQ,CAAA;MAChD,qBAAC,KAAK,OAAN;OAAY,WAAW,qCAAO;OAA9B,UAAA,CACE,oBAAC,gCAAD;QACE,WAAW,qCAAO;QAClB,WAAW;QACC;QACZ,SAAS;OACV,CAAA,GACD,oBAAC,uBAAD;QACE,IAAG;QACH,WAAU;OACX,CAAA,CACS;;MACZ,oBAAC,qBAAD;OAEgB;OACd,WAAW,uBAAuB,YAAY;OACtB;OACxB,uBAAuB;MACxB,GALM,KAKN;KACS;;IACX,+BACC,oBAAC,kBAAD,EAAA,UAAmB,0BAA4C,CAAA;GAE7C;EACE,CAAA,CAAA,EAAA,CAAA,GAC1B,oBAAC,gBAAD,CAAiB,CAAA,CACH;;AAEpB,CACF"}
|
|
1
|
+
{"version":3,"file":"PasswordCreationField.mjs","names":[],"sources":["../../../../../../../src/components/PasswordCreationField/PasswordCreationField.tsx"],"sourcesContent":["import {\n type PropsWithChildren,\n useState,\n type ClipboardEvent,\n useCallback,\n useId,\n useMemo,\n useRef,\n} from \"react\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport styles from \"./PasswordCreationField.module.scss\";\nimport * as Aria from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport { type ActionFn } from \"@/components/Action\";\nimport getStateFromLatestPolicyValidationResult from \"@/components/PasswordCreationField/lib/getStateFromLatestPolicyValidationResult\";\nimport locales from \"./locales/*.locale.json\";\nimport generateValidationTranslation from \"@/components/PasswordCreationField/lib/generateValidationTranslation\";\nimport FieldDescription from \"@/components/FieldDescription\";\nimport ComplexityIndicator from \"@/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator\";\nimport { generatePassword } from \"@/components/PasswordCreationField/worker/generatePassword\";\nimport TogglePasswordVisibilityButton from \"@/components/PasswordCreationField/components/TogglePasswordVisibilityButton/TogglePasswordVisibilityButton\";\nimport { ValidationResultButton } from \"@/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton\";\nimport { PasswordGenerateButton } from \"@/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton\";\nimport type {\n PolicyValidationResult,\n PolicyGenericDeclaration,\n RuleValidationResult,\n} from \"@/integrations/@mittwald/password-tools-js\";\nimport {\n defaultPasswordCreationPolicy,\n Policy,\n} from \"@/integrations/@mittwald/password-tools-js\";\nimport { usePolicyValidationResult } from \"@/components/PasswordCreationField/lib/usePolicyValidationResult\";\nimport { joinIds, useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { FieldError } from \"@/components/FieldError\";\nimport { useControlledHostValueProps } from \"@/lib/remote/useControlledHostValueProps\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\nimport {\n useAriaAnnouncePasswordVisibility,\n useAriaAnnounceValidationState,\n} from \"@/components/PasswordCreationField/lib/ariaAnnounce\";\n\nexport interface PasswordCreationFieldProps\n extends\n PropsWithChildren<\n Omit<Aria.TextFieldProps, \"children\" | \"value\" | \"defaultValue\"> &\n Partial<Pick<Aria.FieldErrorRenderProps, \"validationErrors\">>\n >,\n FlowComponentProps<HTMLInputElement> {\n /** The password of a controlled field. */\n value?: string;\n /** Called with the password and its validity whenever the password changes. */\n onValidationResult?: (result: { password: string; isValid: boolean }) => void;\n /** The initial password of an uncontrolled field. */\n defaultValue?: string;\n /** The placeholder shown while the field is empty. */\n placeholder?: string;\n /**\n * The policy the password is validated against.\n *\n * @default defaultPasswordCreationPolicy\n */\n validationPolicy?: PolicyGenericDeclaration;\n}\n\nexport interface ResolvedPolicyValidationResult extends Omit<\n PolicyValidationResult,\n \"isValid\"\n> {\n isValid: boolean | \"indeterminate\";\n ruleResults: RuleValidationResult[];\n}\n\n/** @flr-generate all */\nexport const PasswordCreationField = flowComponent(\n \"PasswordCreationField\",\n (props) => {\n const {\n children,\n className,\n ref,\n isDisabled,\n onValidationResult,\n isInvalid: invalidFromProps,\n validationPolicy:\n validationPolicyFromProps = defaultPasswordCreationPolicy,\n isRequired,\n value,\n onChange,\n ...rest\n } = useControlledHostValueProps(props, \"\");\n\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n const validationPolicy = useMemo(\n () => Policy.fromDeclaration(validationPolicyFromProps),\n [validationPolicyFromProps],\n );\n\n const [isPasswordRevealed, setIsPasswordRevealed] = useState(false);\n const initialPolicyValidationState: ResolvedPolicyValidationResult = {\n isValid: \"indeterminate\",\n complexity: {\n min: validationPolicy.minComplexity,\n actual: 4,\n warning: null,\n },\n ruleResults: [],\n };\n\n const [policyValidationResult, setPolicyValidationResult] = useState(\n initialPolicyValidationState,\n );\n\n const loadingRef = useRef<ReturnType<typeof setTimeout>>(null);\n const { rememberValidationResult } = usePolicyValidationResult(\n validationPolicy,\n value ?? \"\",\n () => {\n if (isEmptyValue) {\n return;\n }\n\n loadingRef.current = setTimeout(() => {\n setPolicyValidationResult((r) => ({\n ...r,\n isValid: \"indeterminate\",\n }));\n }, 150);\n },\n ({ password, isValid, results }) => {\n if (loadingRef.current) {\n clearTimeout(loadingRef.current);\n }\n\n if (isEmptyValue) {\n setPolicyValidationResult(() => ({\n ...results,\n isValid: true,\n }));\n return;\n }\n\n setPolicyValidationResult(() => results);\n onValidationResult?.({ password, isValid });\n },\n );\n\n const isEmptyValue = !value;\n const stateFromValidationResult = getStateFromLatestPolicyValidationResult(\n isEmptyValue,\n policyValidationResult,\n );\n let latestValidationErrorText = undefined;\n if (stateFromValidationResult) {\n const [translationKey, translationValues] = generateValidationTranslation(\n stateFromValidationResult,\n );\n latestValidationErrorText = translate.format(\n translationKey,\n translationValues,\n );\n }\n\n const isValidFromValidationResult =\n !isEmptyValue && stateFromValidationResult?.isValid;\n\n const isInvalidFromValidationResult =\n !isEmptyValue && stateFromValidationResult?.isValid === false;\n const isInvalid = invalidFromProps || isInvalidFromValidationResult;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n renderedFieldErrorId,\n } = useFieldComponent(props, \"PasswordCreationField\");\n\n /**\n * The result for a valid password appears after the asynchronous policy\n * validation. react-aria resolves its description slot only when the\n * field's validity changes, so a result that appears while the field stays\n * valid (a generated password) was never linked. It gets its own id\n * instead, referenced only while it is rendered.\n *\n * A shown error replaces it: the FormField styles hide descriptions next to\n * an error, and a hidden description would still be announced.\n */\n const resultDescriptionId = useId();\n const [isResultDescriptionRendered, setIsResultDescriptionRendered] =\n useState(false);\n const resultDescriptionRef = useCallback((element: Element | null) => {\n setIsResultDescriptionRendered(!!element);\n }, []);\n const describedBy = joinIds(\n isResultDescriptionRendered && resultDescriptionId,\n controlProps[\"aria-describedby\"],\n );\n\n useAriaAnnounceValidationState(\n latestValidationErrorText,\n !isEmptyValue && policyValidationResult.isValid !== \"indeterminate\",\n );\n useAriaAnnouncePasswordVisibility(isPasswordRevealed);\n\n const setOptimisticPolicyValidationResult = (\n state: Partial<ResolvedPolicyValidationResult> = {},\n ) => {\n setPolicyValidationResult((currentState) => ({\n ...currentState,\n isValid: true,\n ...state,\n }));\n };\n\n const onPasswordGenerateHandler: ActionFn = async () => {\n const generatedPassword = await generatePassword(validationPolicy);\n /**\n * The generator returns only passwords the policy accepts, so the rating\n * is set with the password instead of after the typing debounce. It is\n * the policy's own result: a guessed one (full strength) was overturned\n * by the real rating, e.g. to \"meets the minimum requirements\". Cached,\n * so the debounced validation of this password does not rate it again.\n */\n const generatedPasswordResult =\n await validationPolicy.validate(generatedPassword);\n rememberValidationResult(generatedPassword, generatedPasswordResult);\n setPolicyValidationResult(generatedPasswordResult);\n setIsPasswordRevealed(true);\n onChange(generatedPassword);\n };\n\n const onPasswordPasteHandler = (event: ClipboardEvent) => {\n const pastedValue = event.clipboardData?.getData(\"text\");\n if (typeof pastedValue === \"string\" && pastedValue !== value) {\n setOptimisticPolicyValidationResult({\n isValid: \"indeterminate\",\n });\n }\n };\n\n const togglePasswordVisibilityHandler = () => {\n setIsPasswordRevealed((old) => !old);\n };\n\n const propsContext: PropsContext = {\n ...fieldPropsContext,\n Button: {\n tunnel: {\n id: \"button\",\n component: \"PasswordCreationField\",\n },\n size: \"m\",\n variant: \"plain\",\n color: \"secondary\",\n isDisabled: isDisabled,\n className: styles.button,\n },\n CopyButton: {\n tunnel: {\n id: \"button\",\n component: \"PasswordCreationField\",\n },\n size: \"m\",\n variant: \"plain\",\n color: \"secondary\",\n isDisabled: isDisabled,\n className: styles.button,\n text: value,\n },\n Label: {\n ...fieldPropsContext.Label,\n children: dynamic((localProps) => {\n return (\n <>\n {localProps.children}\n <PasswordGenerateButton\n isDisabled={isDisabled}\n onGeneratePasswordAction={onPasswordGenerateHandler}\n />\n <ValidationResultButton\n isEmptyValue={isEmptyValue}\n isDisabled={isDisabled}\n policyValidationResult={policyValidationResult}\n />\n </>\n );\n }),\n },\n };\n\n return (\n <Aria.TextField\n {...rest}\n aria-describedby={describedBy}\n value={value}\n type={isPasswordRevealed ? \"text\" : \"password\"}\n onChange={onChange}\n onPaste={onPasswordPasteHandler}\n className={clsx(className, wrapperProps.className)}\n isDisabled={isDisabled}\n isInvalid={isInvalid}\n isRequired={isRequired}\n >\n <FieldErrorCaptureContext>\n {latestValidationErrorText && (\n <FieldError>{latestValidationErrorText}</FieldError>\n )}\n <PropsContextProvider\n props={propsContext}\n dependencies={[\n isDisabled,\n isRequired,\n value,\n policyValidationResult,\n isEmptyValue,\n ]}\n >\n {children}\n <Aria.Group\n isDisabled={isDisabled}\n className={clsx(styles.inputGroup)}\n >\n <Aria.Input ref={ref} className={styles.input} />\n <Aria.Group className={styles.buttonContainer}>\n <TogglePasswordVisibilityButton\n className={styles.button}\n isVisible={isPasswordRevealed}\n isDisabled={isDisabled}\n onPress={togglePasswordVisibilityHandler}\n />\n <UiComponentTunnelExit\n id=\"button\"\n component=\"PasswordCreationField\"\n />\n </Aria.Group>\n <ComplexityIndicator\n key={value}\n isEmptyValue={isEmptyValue}\n isLoading={policyValidationResult.isValid === \"indeterminate\"}\n policyValidationResult={policyValidationResult}\n validationResultState={stateFromValidationResult}\n isInvalid={invalidFromProps}\n />\n </Aria.Group>\n {isValidFromValidationResult && !renderedFieldErrorId && (\n // Out of react-aria's description slot, which would set its own\n // id – see `resultDescriptionId`.\n <Aria.TextContext.Provider value={null}>\n <FieldDescription\n id={resultDescriptionId}\n ref={resultDescriptionRef}\n >\n {latestValidationErrorText}\n </FieldDescription>\n </Aria.TextContext.Provider>\n )}\n </PropsContextProvider>\n </FieldErrorCaptureContext>\n <FieldErrorView />\n </Aria.TextField>\n );\n },\n);\n\nexport default PasswordCreationField;\n"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
7
7
|
//#region src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.tsx
|
|
8
8
|
/** @internal */
|
|
9
9
|
var ComplexityIndicator = (props) => {
|
|
10
|
-
const { policyValidationResult, validationResultState, isLoading, isEmptyValue } = props;
|
|
10
|
+
const { policyValidationResult, validationResultState, isLoading, isEmptyValue, isInvalid } = props;
|
|
11
11
|
let complexityVisible;
|
|
12
12
|
let status;
|
|
13
13
|
const complexityScore = policyValidationResult?.complexity;
|
|
@@ -22,7 +22,7 @@ var ComplexityIndicator = (props) => {
|
|
|
22
22
|
status = "success";
|
|
23
23
|
} else {
|
|
24
24
|
complexityVisible = true;
|
|
25
|
-
status = getStatusFromPolicyValidationResult(validationResultState?.isValid ?? policyValidationResult.isValid, policyValidationResult);
|
|
25
|
+
status = isInvalid ? "danger" : getStatusFromPolicyValidationResult(validationResultState?.isValid ?? policyValidationResult.isValid, policyValidationResult);
|
|
26
26
|
}
|
|
27
27
|
const complexityFulfilled = totalFulfilledPercentage === 100;
|
|
28
28
|
const percentageClassName = clsx(ComplexityIndicator_module_default.bar, !isEmptyValue && status !== "unavailable" && ComplexityIndicator_module_default[`bar-background-status-${status}`], {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComplexityIndicator.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport styles from \"./ComplexityIndicator.module.scss\";\nimport { getStatusFromPolicyValidationResult } from \"@/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult\";\nimport clsx from \"clsx\";\nimport type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport { type Status } from \"@/lib/types/props\";\nimport type { StateFromLatestPolicyValidationResult } from \"@/components/PasswordCreationField/lib/getStateFromLatestPolicyValidationResult\";\n\nexport type ComplexityStatus = Exclude<Status, \"info\"> | \"indeterminate\";\n\nexport interface ComplexityIndicatorProps {\n isLoading: boolean;\n isEmptyValue: boolean;\n validationResultState: StateFromLatestPolicyValidationResult;\n policyValidationResult: ResolvedPolicyValidationResult;\n}\n\n/** @internal */\nexport const ComplexityIndicator: FC<ComplexityIndicatorProps> = (props) => {\n const {\n policyValidationResult,\n validationResultState,\n isLoading,\n isEmptyValue,\n } = props;\n\n let complexityVisible;\n let status: ComplexityStatus;\n\n const complexityScore = policyValidationResult?.complexity;\n const rulesResults = policyValidationResult?.ruleResults ?? [];\n\n const complexityFulfilledPercentage = complexityScore\n ? Math.min(\n (100 / (complexityScore.min + 1)) * (complexityScore.actual + 1),\n 100,\n )\n : 0;\n\n const validRules = rulesResults.filter((r) => r.isValid).length;\n const rulesFulfilledPercentage =\n rulesResults.length > 0 ? (validRules / rulesResults.length) * 100 : 0;\n\n let totalFulfilledPercentage = Math.round(\n complexityFulfilledPercentage * 0.8 + rulesFulfilledPercentage * 0.2,\n );\n\n if (isEmptyValue) {\n complexityVisible = false;\n totalFulfilledPercentage = 0;\n status = \"success\";\n } else {\n complexityVisible = true;\n status = getStatusFromPolicyValidationResult(\n
|
|
1
|
+
{"version":3,"file":"ComplexityIndicator.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport styles from \"./ComplexityIndicator.module.scss\";\nimport { getStatusFromPolicyValidationResult } from \"@/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult\";\nimport clsx from \"clsx\";\nimport type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport { type Status } from \"@/lib/types/props\";\nimport type { StateFromLatestPolicyValidationResult } from \"@/components/PasswordCreationField/lib/getStateFromLatestPolicyValidationResult\";\n\nexport type ComplexityStatus = Exclude<Status, \"info\"> | \"indeterminate\";\n\nexport interface ComplexityIndicatorProps {\n isLoading: boolean;\n isEmptyValue: boolean;\n validationResultState: StateFromLatestPolicyValidationResult;\n policyValidationResult: ResolvedPolicyValidationResult;\n /**\n * The field is invalid for a reason outside the policy, e.g. a server error.\n * The bar then shows danger like the field, not the password's strength.\n */\n isInvalid?: boolean;\n}\n\n/** @internal */\nexport const ComplexityIndicator: FC<ComplexityIndicatorProps> = (props) => {\n const {\n policyValidationResult,\n validationResultState,\n isLoading,\n isEmptyValue,\n isInvalid,\n } = props;\n\n let complexityVisible;\n let status: ComplexityStatus;\n\n const complexityScore = policyValidationResult?.complexity;\n const rulesResults = policyValidationResult?.ruleResults ?? [];\n\n const complexityFulfilledPercentage = complexityScore\n ? Math.min(\n (100 / (complexityScore.min + 1)) * (complexityScore.actual + 1),\n 100,\n )\n : 0;\n\n const validRules = rulesResults.filter((r) => r.isValid).length;\n const rulesFulfilledPercentage =\n rulesResults.length > 0 ? (validRules / rulesResults.length) * 100 : 0;\n\n let totalFulfilledPercentage = Math.round(\n complexityFulfilledPercentage * 0.8 + rulesFulfilledPercentage * 0.2,\n );\n\n if (isEmptyValue) {\n complexityVisible = false;\n totalFulfilledPercentage = 0;\n status = \"success\";\n } else {\n complexityVisible = true;\n status = isInvalid\n ? \"danger\"\n : getStatusFromPolicyValidationResult(\n validationResultState?.isValid ?? policyValidationResult.isValid,\n policyValidationResult,\n );\n }\n\n const complexityFulfilled = totalFulfilledPercentage === 100;\n\n const percentageClassName = clsx(\n styles.bar,\n !isEmptyValue &&\n status !== \"unavailable\" &&\n styles[`bar-background-status-${status}`],\n {\n [styles.loading as string]: isLoading,\n [styles.running as string]: !complexityFulfilled,\n },\n );\n\n return (\n <div\n aria-hidden={true}\n data-container=\"complexity\"\n data-complexity-visible={complexityVisible}\n data-complexity-status={status}\n data-complexity-percentage={totalFulfilledPercentage}\n className={clsx(styles.complexityIndicator, {\n [styles.hide as string]: !complexityVisible,\n })}\n >\n <div\n style={{\n \"--complexity-indicator--percentage\": totalFulfilledPercentage,\n }}\n className={percentageClassName}\n />\n </div>\n );\n};\n\nexport default ComplexityIndicator;\n"],"mappings":";;;;;;;;AAuBA,IAAa,uBAAqD,UAAU;CAC1E,MAAM,EACJ,wBACA,uBACA,WACA,cACA,cACE;CAEJ,IAAI;CACJ,IAAI;CAEJ,MAAM,kBAAkB,wBAAwB;CAChD,MAAM,eAAe,wBAAwB,eAAe,CAAC;CAE7D,MAAM,gCAAgC,kBAClC,KAAK,IACF,OAAO,gBAAgB,MAAM,MAAO,gBAAgB,SAAS,IAC9D,GACF,IACA;CAEJ,MAAM,aAAa,aAAa,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC;CACzD,MAAM,2BACJ,aAAa,SAAS,IAAK,aAAa,aAAa,SAAU,MAAM;CAEvE,IAAI,2BAA2B,KAAK,MAClC,gCAAgC,KAAM,2BAA2B,EACnE;CAEA,IAAI,cAAc;EAChB,oBAAoB;EACpB,2BAA2B;EAC3B,SAAS;CACX,OAAO;EACL,oBAAoB;EACpB,SAAS,YACL,WACA,oCACE,uBAAuB,WAAW,uBAAuB,SACzD,sBACF;CACN;CAEA,MAAM,sBAAsB,6BAA6B;CAEzD,MAAM,sBAAsB,KAC1B,mCAAO,KACP,CAAC,gBACC,WAAW,iBACX,mCAAO,yBAAyB,WAClC;GACG,mCAAO,UAAoB;GAC3B,mCAAO,UAAoB,CAAC;CAC/B,CACF;CAEA,OACE,oBAAC,OAAD;EACE,eAAa;EACb,kBAAe;EACf,2BAAyB;EACzB,0BAAwB;EACxB,8BAA4B;EAC5B,WAAW,KAAK,mCAAO,qBAAqB,GACzC,mCAAO,OAAiB,CAAC,kBAC5B,CAAC;EAED,UAAA,oBAAC,OAAD;GACE,OAAO,EACL,sCAAsC,yBACxC;GACA,WAAW;EACZ,CAAA;CACE,CAAA;AAET"}
|
|
@@ -34,6 +34,18 @@ var usePolicyValidationResult = (validationPolicy, password, onValidationStart,
|
|
|
34
34
|
if (password) validatePasswordDebounce(password);
|
|
35
35
|
else validatePassword(password);
|
|
36
36
|
}, [password, validationPolicy]);
|
|
37
|
+
/**
|
|
38
|
+
* Stores a result the caller already has (a generated password), so the
|
|
39
|
+
* validation of that password answers from the cache instead of rating it
|
|
40
|
+
* again.
|
|
41
|
+
*/
|
|
42
|
+
const rememberValidationResult = (pwd, results) => {
|
|
43
|
+
cache.current = {
|
|
44
|
+
password: pwd,
|
|
45
|
+
results
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
return { rememberValidationResult };
|
|
37
49
|
};
|
|
38
50
|
//#endregion
|
|
39
51
|
export { usePolicyValidationResult };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePolicyValidationResult.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/usePolicyValidationResult.ts"],"sourcesContent":["import { startTransition, useEffect, useRef } from \"react\";\nimport type { Policy } from \"@/integrations/@mittwald/password-tools-js\";\nimport type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport { useDebouncedCallback } from \"use-debounce\";\n\n/** @internal */\nexport const usePolicyValidationResult = (\n validationPolicy: Policy,\n password: string,\n onValidationStart?: () => void,\n onValidationResult?: (data: {\n password: string;\n isValid: boolean;\n results: ResolvedPolicyValidationResult;\n }) => void,\n) => {\n const cache = useRef<{\n password: string;\n results: ResolvedPolicyValidationResult;\n } | null>(null);\n\n const validatePassword = (pwd: string) => {\n onValidationStart?.();\n\n startTransition(async () => {\n if (cache.current?.password === pwd) {\n onValidationResult?.({\n password: cache.current.password,\n isValid: Boolean(cache.current.results.isValid),\n results: cache.current.results,\n });\n return;\n }\n\n const validationResult = await validationPolicy.validate(pwd);\n cache.current = { password: pwd, results: validationResult };\n onValidationResult?.({\n password: pwd,\n isValid: validationResult.isValid,\n results: validationResult,\n });\n });\n };\n\n const validatePasswordDebounce = useDebouncedCallback(validatePassword, 350, {\n trailing: true,\n });\n\n useEffect(() => {\n if (password) {\n validatePasswordDebounce(password);\n } else {\n validatePassword(password);\n }\n }, [password, validationPolicy]);\n};\n"],"mappings":";;;;;;AAMA,IAAa,6BACX,kBACA,UACA,mBACA,uBAKG;CACH,MAAM,QAAQ,OAGJ,IAAI;CAEd,MAAM,oBAAoB,QAAgB;EACxC,oBAAoB;EAEpB,gBAAgB,YAAY;GAC1B,IAAI,MAAM,SAAS,aAAa,KAAK;IACnC,qBAAqB;KACnB,UAAU,MAAM,QAAQ;KACxB,SAAS,QAAQ,MAAM,QAAQ,QAAQ,OAAO;KAC9C,SAAS,MAAM,QAAQ;IACzB,CAAC;IACD;GACF;GAEA,MAAM,mBAAmB,MAAM,iBAAiB,SAAS,GAAG;GAC5D,MAAM,UAAU;IAAE,UAAU;IAAK,SAAS;GAAiB;GAC3D,qBAAqB;IACnB,UAAU;IACV,SAAS,iBAAiB;IAC1B,SAAS;GACX,CAAC;EACH,CAAC;CACH;CAEA,MAAM,2BAA2B,qBAAqB,kBAAkB,KAAK,EAC3E,UAAU,KACZ,CAAC;CAED,gBAAgB;EACd,IAAI,UACF,yBAAyB,QAAQ;OAEjC,iBAAiB,QAAQ;CAE7B,GAAG,CAAC,UAAU,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"usePolicyValidationResult.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/usePolicyValidationResult.ts"],"sourcesContent":["import { startTransition, useEffect, useRef } from \"react\";\nimport type { Policy } from \"@/integrations/@mittwald/password-tools-js\";\nimport type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport { useDebouncedCallback } from \"use-debounce\";\n\n/** @internal */\nexport const usePolicyValidationResult = (\n validationPolicy: Policy,\n password: string,\n onValidationStart?: () => void,\n onValidationResult?: (data: {\n password: string;\n isValid: boolean;\n results: ResolvedPolicyValidationResult;\n }) => void,\n) => {\n const cache = useRef<{\n password: string;\n results: ResolvedPolicyValidationResult;\n } | null>(null);\n\n const validatePassword = (pwd: string) => {\n onValidationStart?.();\n\n startTransition(async () => {\n if (cache.current?.password === pwd) {\n onValidationResult?.({\n password: cache.current.password,\n isValid: Boolean(cache.current.results.isValid),\n results: cache.current.results,\n });\n return;\n }\n\n const validationResult = await validationPolicy.validate(pwd);\n cache.current = { password: pwd, results: validationResult };\n onValidationResult?.({\n password: pwd,\n isValid: validationResult.isValid,\n results: validationResult,\n });\n });\n };\n\n const validatePasswordDebounce = useDebouncedCallback(validatePassword, 350, {\n trailing: true,\n });\n\n useEffect(() => {\n if (password) {\n validatePasswordDebounce(password);\n } else {\n validatePassword(password);\n }\n }, [password, validationPolicy]);\n\n /**\n * Stores a result the caller already has (a generated password), so the\n * validation of that password answers from the cache instead of rating it\n * again.\n */\n const rememberValidationResult = (\n pwd: string,\n results: ResolvedPolicyValidationResult,\n ) => {\n cache.current = { password: pwd, results };\n };\n\n return { rememberValidationResult } as const;\n};\n"],"mappings":";;;;;;AAMA,IAAa,6BACX,kBACA,UACA,mBACA,uBAKG;CACH,MAAM,QAAQ,OAGJ,IAAI;CAEd,MAAM,oBAAoB,QAAgB;EACxC,oBAAoB;EAEpB,gBAAgB,YAAY;GAC1B,IAAI,MAAM,SAAS,aAAa,KAAK;IACnC,qBAAqB;KACnB,UAAU,MAAM,QAAQ;KACxB,SAAS,QAAQ,MAAM,QAAQ,QAAQ,OAAO;KAC9C,SAAS,MAAM,QAAQ;IACzB,CAAC;IACD;GACF;GAEA,MAAM,mBAAmB,MAAM,iBAAiB,SAAS,GAAG;GAC5D,MAAM,UAAU;IAAE,UAAU;IAAK,SAAS;GAAiB;GAC3D,qBAAqB;IACnB,UAAU;IACV,SAAS,iBAAiB;IAC1B,SAAS;GACX,CAAC;EACH,CAAC;CACH;CAEA,MAAM,2BAA2B,qBAAqB,kBAAkB,KAAK,EAC3E,UAAU,KACZ,CAAC;CAED,gBAAgB;EACd,IAAI,UACF,yBAAyB,QAAQ;OAEjC,iBAAiB,QAAQ;CAE7B,GAAG,CAAC,UAAU,gBAAgB,CAAC;;;;;;CAO/B,MAAM,4BACJ,KACA,YACG;EACH,MAAM,UAAU;GAAE,UAAU;GAAK;EAAQ;CAC3C;CAEA,OAAO,EAAE,yBAAyB;AACpC"}
|
|
@@ -16,7 +16,7 @@ import * as Aria from "react-aria-components";
|
|
|
16
16
|
/** @flr-generate all */
|
|
17
17
|
var RadioGroup = flowComponent("RadioGroup", (props) => {
|
|
18
18
|
const { children, className, s, m, l, ref, ...rest } = props;
|
|
19
|
-
const { FieldErrorView, FieldErrorCaptureContext,
|
|
19
|
+
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext } = useFieldComponent(props, "RadioGroup");
|
|
20
20
|
const rootClassName = clsx(FormField_module_default.formField, className);
|
|
21
21
|
const propsContext = {
|
|
22
22
|
RadioButton: { tunnel: {
|
|
@@ -33,7 +33,8 @@ var RadioGroup = flowComponent("RadioGroup", (props) => {
|
|
|
33
33
|
useMakeFocusable(localRadioRef);
|
|
34
34
|
return /* @__PURE__ */ jsxs(Aria.RadioGroup, {
|
|
35
35
|
...rest,
|
|
36
|
-
|
|
36
|
+
"aria-describedby": controlProps["aria-describedby"],
|
|
37
|
+
className: clsx(rootClassName, wrapperProps.className),
|
|
37
38
|
ref: localRadioRef,
|
|
38
39
|
children: [/* @__PURE__ */ jsx(FieldErrorCaptureContext, { children: /* @__PURE__ */ jsxs(PropsContextProvider, {
|
|
39
40
|
props: propsContext,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioGroup.mjs","names":[],"sources":["../../../../../../../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport styles from \"./RadioGroup.module.scss\";\nimport * as Aria from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport type { ColumnLayoutProps } from \"@/components/ColumnLayout\";\nimport { ColumnLayout } from \"@/components/ColumnLayout\";\nimport formFieldStyles from \"@/components/FormField/FormField.module.scss\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useMakeFocusable } from \"@/lib/hooks/dom/useMakeFocusable\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\n\nexport interface RadioGroupProps\n extends\n PropsWithChildren<Omit<Aria.RadioGroupProps, \"children\">>,\n FlowComponentProps,\n Pick<ColumnLayoutProps, \"s\" | \"m\" | \"l\"> {}\n\n/** @flr-generate all */\nexport const RadioGroup = flowComponent(\"RadioGroup\", (props) => {\n const { children, className, s, m, l, ref, ...rest } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n
|
|
1
|
+
{"version":3,"file":"RadioGroup.mjs","names":[],"sources":["../../../../../../../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport styles from \"./RadioGroup.module.scss\";\nimport * as Aria from \"react-aria-components\";\nimport clsx from \"clsx\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport type { ColumnLayoutProps } from \"@/components/ColumnLayout\";\nimport { ColumnLayout } from \"@/components/ColumnLayout\";\nimport formFieldStyles from \"@/components/FormField/FormField.module.scss\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useMakeFocusable } from \"@/lib/hooks/dom/useMakeFocusable\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\n\nexport interface RadioGroupProps\n extends\n PropsWithChildren<Omit<Aria.RadioGroupProps, \"children\">>,\n FlowComponentProps,\n Pick<ColumnLayoutProps, \"s\" | \"m\" | \"l\"> {}\n\n/** @flr-generate all */\nexport const RadioGroup = flowComponent(\"RadioGroup\", (props) => {\n const { children, className, s, m, l, ref, ...rest } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"RadioGroup\");\n\n const rootClassName = clsx(formFieldStyles.formField, className);\n const propsContext: PropsContext = {\n RadioButton: {\n tunnel: {\n id: \"radioButtons\",\n component: \"RadioGroup\",\n },\n },\n Radio: {\n tunnel: {\n id: \"radios\",\n component: \"RadioGroup\",\n },\n },\n ...fieldPropsContext,\n };\n\n const localRadioRef = useObjectRef(ref);\n useMakeFocusable(localRadioRef);\n\n return (\n <Aria.RadioGroup\n {...rest}\n aria-describedby={controlProps[\"aria-describedby\"]}\n className={clsx(rootClassName, wrapperProps.className)}\n ref={localRadioRef}\n >\n <FieldErrorCaptureContext>\n <PropsContextProvider props={propsContext}>\n <ColumnLayout s={s} m={m} l={l} className={styles.radioGroup}>\n <UiComponentTunnelExit id=\"radioButtons\" component=\"RadioGroup\" />\n </ColumnLayout>\n\n <ColumnLayout\n s={s ?? [1]}\n m={m ?? [1]}\n l={l ?? [1]}\n rowGap=\"s\"\n className={styles.radioGroup}\n >\n <UiComponentTunnelExit id=\"radios\" component=\"RadioGroup\" />\n </ColumnLayout>\n\n {children}\n </PropsContextProvider>\n </FieldErrorCaptureContext>\n <FieldErrorView />\n </Aria.RadioGroup>\n );\n});\n\nexport default RadioGroup;\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,IAAa,aAAa,cAAc,eAAe,UAAU;CAC/D,MAAM,EAAE,UAAU,WAAW,GAAG,GAAG,GAAG,KAAK,GAAG,SAAS;CAEvD,MAAM,EACJ,gBACA,0BACA,cACA,cACA,sBACE,kBAAkB,OAAO,YAAY;CAEzC,MAAM,gBAAgB,KAAK,yBAAgB,WAAW,SAAS;CAC/D,MAAM,eAA6B;EACjC,aAAa,EACX,QAAQ;GACN,IAAI;GACJ,WAAW;EACb,EACF;EACA,OAAO,EACL,QAAQ;GACN,IAAI;GACJ,WAAW;EACb,EACF;EACA,GAAG;CACL;CAEA,MAAM,gBAAgB,aAAa,GAAG;CACtC,iBAAiB,aAAa;CAE9B,OACE,qBAAC,KAAK,YAAN;EACE,GAAI;EACJ,oBAAkB,aAAa;EAC/B,WAAW,KAAK,eAAe,aAAa,SAAS;EACrD,KAAK;EAJP,UAAA,CAME,oBAAC,0BAAD,EAAA,UACE,qBAAC,sBAAD;GAAsB,OAAO;GAA7B,UAAA;IACE,oBAAC,cAAD;KAAiB;KAAM;KAAM;KAAG,WAAW,0BAAO;KAChD,UAAA,oBAAC,uBAAD;MAAuB,IAAG;MAAe,WAAU;KAAc,CAAA;IACrD,CAAA;IAEd,oBAAC,cAAD;KACE,GAAG,KAAK,CAAC,CAAC;KACV,GAAG,KAAK,CAAC,CAAC;KACV,GAAG,KAAK,CAAC,CAAC;KACV,QAAO;KACP,WAAW,0BAAO;KAElB,UAAA,oBAAC,uBAAD;MAAuB,IAAG;MAAS,WAAU;KAAc,CAAA;IAC/C,CAAA;IAEb;GACmB;EACE,CAAA,EAAA,CAAA,GAC1B,oBAAC,gBAAD,CAAiB,CAAA,CACF;;AAErB,CAAC"}
|
|
@@ -22,8 +22,8 @@ var toSegmentValue = (value) => value === void 0 ? void 0 : Math.round(value).to
|
|
|
22
22
|
*/
|
|
23
23
|
var Rating = flowComponent("Rating", (props) => {
|
|
24
24
|
const { value, defaultValue, size = "m", maxValue = 5, fill = "cumulative", className, children, ref, iconEmpty, iconFilled, ...rest } = props;
|
|
25
|
-
const { FieldErrorView, FieldErrorCaptureContext,
|
|
26
|
-
const rootClassName = clsx(Rating_module_default.rating, Rating_module_default[`size-${size}`], Rating_module_default[`fill-${fill}`],
|
|
25
|
+
const { FieldErrorView, FieldErrorCaptureContext, wrapperProps, controlProps, fieldPropsContext } = useFieldComponent(props, "Rating");
|
|
26
|
+
const rootClassName = clsx(Rating_module_default.rating, Rating_module_default[`size-${size}`], Rating_module_default[`fill-${fill}`], wrapperProps.className, className);
|
|
27
27
|
const localRef = useObjectRef(ref);
|
|
28
28
|
useMakeFocusable(localRef);
|
|
29
29
|
const segmentProps = {
|
|
@@ -44,6 +44,7 @@ var Rating = flowComponent("Rating", (props) => {
|
|
|
44
44
|
const defaultSegments = Array.from({ length: maxValue }, (_, index) => /* @__PURE__ */ jsx(RatingSegment, { ...segmentProps }, index));
|
|
45
45
|
return /* @__PURE__ */ jsxs(Aria.RadioGroup, {
|
|
46
46
|
...rest,
|
|
47
|
+
"aria-describedby": controlProps["aria-describedby"],
|
|
47
48
|
className: rootClassName,
|
|
48
49
|
value: toSegmentValue(value),
|
|
49
50
|
defaultValue: toSegmentValue(defaultValue),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Rating.mjs","names":[],"sources":["../../../../../../../src/components/Rating/Rating.tsx"],"sourcesContent":["import { Children, type PropsWithChildren, type ReactElement } from \"react\";\nimport styles from \"./Rating.module.scss\";\nimport clsx from \"clsx\";\nimport * as Aria from \"react-aria-components\";\nimport { RatingSegment } from \"@/components/Rating/components/RatingSegment\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport { type PropsContext, PropsContextProvider } from \"@/lib/propsContext\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useMakeFocusable } from \"@/lib/hooks/dom/useMakeFocusable\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\nimport { RatingSegmentContextProvider } from \"@/components/Rating/context\";\n\nexport interface RatingProps\n extends\n FlowComponentProps,\n PropsWithChildren,\n Omit<Aria.RadioGroupProps, \"children\" | \"value\" | \"defaultValue\"> {\n /**\n * The value sets the amount of filled stars. Decimals are rounded to the\n * nearest whole star. @default: 0\n */\n value?: number;\n /**\n * The defaultValue sets the amount of default filled stars. Decimals are\n * rounded to the nearest whole star. @default: 0\n */\n defaultValue?: number;\n /** The size of the component. @default: \"m\" */\n size?: \"s\" | \"m\";\n /**\n * The number of segments the rating consists of. Ignored when the rating has\n * `RatingSegment` children — those define the number of segments themselves.\n *\n * @default: 5\n */\n maxValue?: number;\n /**\n * How the segments are filled. `cumulative` fills every segment up to the\n * value, `single` fills only the selected segment.\n *\n * @default: cumulative\n */\n fill?: \"cumulative\" | \"single\";\n /** An alternative icon for the empty state */\n iconEmpty?: ReactElement;\n /** An alternative icon for the filled state */\n iconFilled?: ReactElement;\n}\n\nconst segmentsTunnelId = \"segments\";\n\n// Segment values are whole numbers, so a decimal would match no segment.\nconst toSegmentValue = (value?: number) =>\n value === undefined ? undefined : Math.round(value).toString();\n\n/**\n * @flr-generate all\n * @flr-slot-props iconEmpty, iconFilled\n */\nexport const Rating = flowComponent(\"Rating\", (props) => {\n const {\n value,\n defaultValue,\n size = \"m\",\n maxValue = 5,\n fill = \"cumulative\",\n className,\n children,\n ref,\n iconEmpty,\n iconFilled,\n ...rest\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n
|
|
1
|
+
{"version":3,"file":"Rating.mjs","names":[],"sources":["../../../../../../../src/components/Rating/Rating.tsx"],"sourcesContent":["import { Children, type PropsWithChildren, type ReactElement } from \"react\";\nimport styles from \"./Rating.module.scss\";\nimport clsx from \"clsx\";\nimport * as Aria from \"react-aria-components\";\nimport { RatingSegment } from \"@/components/Rating/components/RatingSegment\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport { type PropsContext, PropsContextProvider } from \"@/lib/propsContext\";\nimport { useFieldComponent } from \"@/lib/hooks/useFieldComponent\";\nimport { useObjectRef } from \"@react-aria/utils\";\nimport { useMakeFocusable } from \"@/lib/hooks/dom/useMakeFocusable\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\nimport { RatingSegmentContextProvider } from \"@/components/Rating/context\";\n\nexport interface RatingProps\n extends\n FlowComponentProps,\n PropsWithChildren,\n Omit<Aria.RadioGroupProps, \"children\" | \"value\" | \"defaultValue\"> {\n /**\n * The value sets the amount of filled stars. Decimals are rounded to the\n * nearest whole star. @default: 0\n */\n value?: number;\n /**\n * The defaultValue sets the amount of default filled stars. Decimals are\n * rounded to the nearest whole star. @default: 0\n */\n defaultValue?: number;\n /** The size of the component. @default: \"m\" */\n size?: \"s\" | \"m\";\n /**\n * The number of segments the rating consists of. Ignored when the rating has\n * `RatingSegment` children — those define the number of segments themselves.\n *\n * @default: 5\n */\n maxValue?: number;\n /**\n * How the segments are filled. `cumulative` fills every segment up to the\n * value, `single` fills only the selected segment.\n *\n * @default: cumulative\n */\n fill?: \"cumulative\" | \"single\";\n /** An alternative icon for the empty state */\n iconEmpty?: ReactElement;\n /** An alternative icon for the filled state */\n iconFilled?: ReactElement;\n}\n\nconst segmentsTunnelId = \"segments\";\n\n// Segment values are whole numbers, so a decimal would match no segment.\nconst toSegmentValue = (value?: number) =>\n value === undefined ? undefined : Math.round(value).toString();\n\n/**\n * @flr-generate all\n * @flr-slot-props iconEmpty, iconFilled\n */\nexport const Rating = flowComponent(\"Rating\", (props) => {\n const {\n value,\n defaultValue,\n size = \"m\",\n maxValue = 5,\n fill = \"cumulative\",\n className,\n children,\n ref,\n iconEmpty,\n iconFilled,\n ...rest\n } = props;\n\n const {\n FieldErrorView,\n FieldErrorCaptureContext,\n wrapperProps,\n controlProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"Rating\");\n\n const rootClassName = clsx(\n styles.rating,\n styles[`size-${size}`],\n styles[`fill-${fill}`],\n wrapperProps.className,\n className,\n );\n\n const localRef = useObjectRef(ref);\n\n useMakeFocusable(localRef);\n\n const segmentProps = { size, iconEmpty, iconFilled };\n\n const propsContext: PropsContext = {\n ...fieldPropsContext,\n RatingSegment: {\n ...segmentProps,\n tunnel: { id: segmentsTunnelId, component: \"Rating\" },\n },\n };\n\n const defaultSegments = Array.from({ length: maxValue }, (_, index) => (\n <RatingSegment key={index} {...segmentProps} />\n ));\n\n return (\n <Aria.RadioGroup\n {...rest}\n aria-describedby={controlProps[\"aria-describedby\"]}\n className={rootClassName}\n value={toSegmentValue(value)}\n defaultValue={toSegmentValue(defaultValue)}\n ref={localRef}\n >\n <FieldErrorCaptureContext>\n <PropsContextProvider\n props={propsContext}\n dependencies={[size, iconEmpty, iconFilled]}\n >\n {children}\n </PropsContextProvider>\n <div className={styles.ratingSegments}>\n <UiComponentTunnelExit id={segmentsTunnelId} component=\"Rating\">\n {(tunnelChildren) => {\n const tunneledSegments = Children.toArray(tunnelChildren);\n const segments =\n tunneledSegments.length > 0\n ? tunneledSegments\n : defaultSegments;\n\n return segments.map((segment, index) => (\n <RatingSegmentContextProvider\n key={index}\n value={{ value: index + 1, count: segments.length }}\n >\n {segment}\n </RatingSegmentContextProvider>\n ));\n }}\n </UiComponentTunnelExit>\n </div>\n </FieldErrorCaptureContext>\n <FieldErrorView />\n </Aria.RadioGroup>\n );\n});\n\nexport default Rating;\n"],"mappings":";;;;;;;;;;;;;;;;AAqDA,IAAM,mBAAmB;AAGzB,IAAM,kBAAkB,UACtB,UAAU,KAAA,IAAY,KAAA,IAAY,KAAK,MAAM,KAAK,CAAC,CAAC,SAAS;;;;;AAM/D,IAAa,SAAS,cAAc,WAAW,UAAU;CACvD,MAAM,EACJ,OACA,cACA,OAAO,KACP,WAAW,GACX,OAAO,cACP,WACA,UACA,KACA,WACA,YACA,GAAG,SACD;CAEJ,MAAM,EACJ,gBACA,0BACA,cACA,cACA,sBACE,kBAAkB,OAAO,QAAQ;CAErC,MAAM,gBAAgB,KACpB,sBAAO,QACP,sBAAO,QAAQ,SACf,sBAAO,QAAQ,SACf,aAAa,WACb,SACF;CAEA,MAAM,WAAW,aAAa,GAAG;CAEjC,iBAAiB,QAAQ;CAEzB,MAAM,eAAe;EAAE;EAAM;EAAW;CAAW;CAEnD,MAAM,eAA6B;EACjC,GAAG;EACH,eAAe;GACb,GAAG;GACH,QAAQ;IAAE,IAAI;IAAkB,WAAW;GAAS;EACtD;CACF;CAEA,MAAM,kBAAkB,MAAM,KAAK,EAAE,QAAQ,SAAS,IAAI,GAAG,UAC3D,oBAAC,eAAD,EAA2B,GAAI,aAAe,GAA1B,KAA0B,CAC/C;CAED,OACE,qBAAC,KAAK,YAAN;EACE,GAAI;EACJ,oBAAkB,aAAa;EAC/B,WAAW;EACX,OAAO,eAAe,KAAK;EAC3B,cAAc,eAAe,YAAY;EACzC,KAAK;EANP,UAAA,CAQE,qBAAC,0BAAD,EAAA,UAAA,CACE,oBAAC,sBAAD;GACE,OAAO;GACP,cAAc;IAAC;IAAM;IAAW;GAAU;GAEzC;EACmB,CAAA,GACtB,oBAAC,OAAD;GAAK,WAAW,sBAAO;GACrB,UAAA,oBAAC,uBAAD;IAAuB,IAAI;IAAkB,WAAU;IACnD,WAAA,mBAAmB;KACnB,MAAM,mBAAmB,SAAS,QAAQ,cAAc;KACxD,MAAM,WACJ,iBAAiB,SAAS,IACtB,mBACA;KAEN,OAAO,SAAS,KAAK,SAAS,UAC5B,oBAAC,8BAAD;MAEE,OAAO;OAAE,OAAO,QAAQ;OAAG,OAAO,SAAS;MAAO;MAEjD,UAAA;KAC2B,GAJvB,KAIuB,CAC/B;IACH;GACqB,CAAA;EACpB,CAAA,CACmB,EAAA,CAAA,GAC1B,oBAAC,gBAAD,CAAiB,CAAA,CACF;;AAErB,CAAC"}
|