@mittwald/flow-react-components 1.3.0-next.1 → 1.3.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +14 -0
- package/dist/assets/component-index.json +1 -1
- package/dist/assets/doc-properties.json +1 -1
- package/dist/css/all-layered.css +1 -1
- package/dist/css/all.css +1 -1
- package/dist/js/_virtual/_28.locale.mjs +10 -0
- package/dist/js/default.mjs +2 -1
- package/dist/js/flr-universal.mjs +2 -1
- package/dist/js/packages/components/src/components/Action/models/ActionModel.mjs +25 -8
- package/dist/js/packages/components/src/components/Action/models/ActionModel.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.mjs +6 -2
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/Area/Area.mjs +3 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/Area/Area.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/Bar/Bar.mjs +12 -3
- package/dist/js/packages/components/src/components/CartesianChart/components/Bar/Bar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/context.mjs +4 -1
- package/dist/js/packages/components/src/components/CartesianChart/context.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/hooks/useScopedStackId.mjs +16 -0
- package/dist/js/packages/components/src/components/CartesianChart/hooks/useScopedStackId.mjs.map +1 -0
- package/dist/js/packages/components/src/components/Combine/Combine.mjs +4 -1
- package/dist/js/packages/components/src/components/Combine/Combine.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Combine/Combine.module.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ContextMenu/ContextMenu.mjs +2 -2
- package/dist/js/packages/components/src/components/ContextMenu/ContextMenu.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ContextMenu/components/ContextMenuSection/ContextMenuSection.mjs +2 -2
- package/dist/js/packages/components/src/components/ContextMenu/components/ContextMenuSection/ContextMenuSection.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ContextMenu/lib.mjs +7 -3
- package/dist/js/packages/components/src/components/ContextMenu/lib.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Icon/components/icons/IconAIHosting.mjs +19 -0
- package/dist/js/packages/components/src/components/Icon/components/icons/IconAIHosting.mjs.map +1 -0
- package/dist/js/packages/components/src/components/Modal/Modal.mjs +6 -4
- package/dist/js/packages/components/src/components/Modal/Modal.mjs.map +1 -1
- package/dist/js/packages/components/src/components/OverlayTrigger/OverlayTrigger.mjs +1 -0
- package/dist/js/packages/components/src/components/OverlayTrigger/OverlayTrigger.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs +8 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton.mjs +2 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.mjs +13 -7
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.module.mjs +9 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.module.mjs.map +1 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry.mjs +12 -4
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/ariaAnnounce.mjs +52 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/ariaAnnounce.mjs.map +1 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/generateValidationTranslation.mjs +1 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/generateValidationTranslation.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult.mjs +1 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/usePolicyValidationResult.mjs +1 -0
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/usePolicyValidationResult.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Popover/components/NonModalPopoverContent/NonModalPopoverContent.mjs +19 -11
- package/dist/js/packages/components/src/components/Popover/components/NonModalPopoverContent/NonModalPopoverContent.mjs.map +1 -1
- package/dist/js/packages/components/src/components/TextArea/TextArea.mjs +14 -13
- package/dist/js/packages/components/src/components/TextArea/TextArea.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Tooltip/Tooltip.module.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/controller/overlay/OverlayContextProvider.mjs +6 -3
- package/dist/js/packages/components/src/lib/controller/overlay/OverlayContextProvider.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/controller/overlay/OverlayController.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/controller/overlay/context.mjs +1 -1
- package/dist/js/packages/components/src/lib/controller/overlay/context.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/controller/overlay/useOverlayController.mjs +1 -1
- package/dist/js/packages/components/src/lib/controller/overlay/useOverlayController.mjs.map +1 -1
- package/dist/types/components/Action/models/ActionModel.d.ts +12 -4
- package/dist/types/components/Action/types.d.ts +9 -2
- package/dist/types/components/CartesianChart/context.d.ts +6 -0
- package/dist/types/components/CartesianChart/hooks/useScopedStackId.d.ts +6 -0
- package/dist/types/components/ContextMenu/lib.d.ts +5 -1
- package/dist/types/components/Icon/components/icons/IconAIHosting.d.ts +4 -0
- package/dist/types/components/Icon/components/icons/index.d.ts +1 -0
- package/dist/types/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton.d.ts +0 -7
- package/dist/types/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.d.ts +0 -9
- package/dist/types/components/PasswordCreationField/lib/ariaAnnounce.d.ts +1 -0
- package/dist/types/components/PasswordCreationField/lib/generateValidationTranslation.d.ts +0 -2
- package/dist/types/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult.d.ts +0 -3
- package/dist/types/components/PasswordCreationField/lib/usePolicyValidationResult.d.ts +1 -7
- package/dist/types/lib/controller/overlay/OverlayContextProvider.d.ts +9 -0
- package/dist/types/lib/controller/overlay/OverlayController.d.ts +11 -1
- package/dist/types/lib/controller/overlay/context.d.ts +19 -2
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.mjs","names":[],"sources":["../../../../../../../src/components/Modal/Modal.tsx"],"sourcesContent":["import { type PropsWithChildren, type ReactNode, Suspense, useId } from \"react\";\nimport styles from \"./Modal.module.scss\";\nimport clsx from \"clsx\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport { OverlayController } from \"@/lib/controller/overlay\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { Overlay, type OverlayProps } from \"@/components/Overlay/Overlay\";\nimport { Action } from \"@/components/Action\";\nimport { IconClose } from \"@/components/Icon/components/icons\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport ButtonView from \"@/views/ButtonView\";\nimport DivView from \"@/views/DivView\";\nimport { OffCanvasSuspenseFallback } from \"@/components/Modal/components/OffCanvasSuspenseFallback\";\nimport { ConfirmUnsavedChangesModal } from \"@/components/Modal/components/ConfirmUnsavedChangesModal/ConfirmUnsavedChangesModal\";\nimport Wrap from \"@/components/Wrap\";\nimport { ClearPropsContext } from \"@/components/ClearPropsContext/ClearPropsContext\";\nimport ClearPropsContextView from \"@/views/ClearPropsContextView\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider\";\nimport { useVirtualKeyboardVisible } from \"@/lib/hooks/dom/useVirtualKeyboardVisible\";\nimport locales from \"./locales/*.locale.json\";\n\ntype SupportedOverlayProps = Pick<\n OverlayProps,\n \"isOpen\" | \"isDefaultOpen\" | \"onOpen\" | \"onClose\" | \"onOpenChange\"\n>;\n\nexport interface ModalProps\n extends\n PropsWithChildren,\n FlowComponentProps,\n PropsWithClassName,\n SupportedOverlayProps {\n /** The size of the modal. @default \"s\" */\n size?: \"s\" | \"m\" | \"l\";\n /** Whether the modal should be displayed as an off canvas. */\n offCanvas?: boolean;\n /**\n * Whether the off canvas should be displayed on the right or left side of the\n * screen. @default \"right\"\n */\n offCanvasOrientation?: \"left\" | \"right\";\n /** An overlay controller to control the modal state. */\n controller?: OverlayController;\n /**\n * Accepts \"actionConfirm\" to use the modal as a confirmation modal for an\n * action.\n */\n slot?: string;\n /** Whether the modal can be closed by clicking outside of it. */\n isDismissable?: boolean;\n /** Whether the close button should be visible */\n showCloseButton?: boolean;\n /**\n * Whether closing the modal must be confirmed – use it to protect unsaved\n * changes.\n */\n confirmOnClose?: boolean;\n}\n\nexport const Modal = flowComponent(\"Modal\", (props) => {\n const {\n size = \"s\",\n offCanvas,\n controller,\n children,\n ref,\n className,\n offCanvasOrientation = \"right\",\n showCloseButton,\n ...overlayProps\n } = props;\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"Modal\");\n\n // On mobile the header/footer are docked (sticky) while at rest, but flow\n // normally while the on-screen keyboard is open so the content gets the full\n // available space (see Modal.module.scss). #2423\n const keyboardVisible = useVirtualKeyboardVisible();\n\n const rootClassName = clsx(\n offCanvas ? styles.offCanvas : styles.modal,\n styles[`size-${size}`],\n offCanvasOrientation === \"left\" && styles[\"left\"],\n keyboardVisible && styles.keyboardVisible,\n className,\n );\n\n const generatedId = useId();\n\n const header = (children: ReactNode) => (\n <>\n <DivView className={styles.headerTitle}>{children}</DivView>\n <ClearPropsContext>\n <ClearPropsContextView>\n <Action closeModal={{ bypassConfirmation: true }}>\n <ButtonView\n variant=\"plain\"\n color=\"secondary\"\n aria-label={stringFormatter.format(\"close\")}\n className={clsx(\n styles.closeButton,\n showCloseButton === true\n ? styles.alwaysVisible\n : showCloseButton === false\n ? styles.alwaysHidden\n : undefined,\n )}\n >\n <IconClose />\n </ButtonView>\n </Action>\n </ClearPropsContextView>\n </ClearPropsContext>\n </>\n );\n\n const nestedHeadingLevel = 3;\n\n const nestedHeadingProps: PropsContext = {\n Heading: { level: nestedHeadingLevel },\n Section: {\n Header: { Heading: { level: nestedHeadingLevel } },\n Heading: { level: nestedHeadingLevel },\n hideSeparator: true,\n },\n Header: { Heading: { level: nestedHeadingLevel } },\n };\n\n const propsContext: PropsContext = {\n Content: {\n ...nestedHeadingProps,\n className: styles.content,\n },\n ColumnLayout: {\n ...nestedHeadingProps,\n l: [2, 1],\n m: [1],\n className: styles.columnLayout,\n AccentBox: { className: styles.accentBox, backgroundColor: \"neutral\" },\n wrapWith: <ClearPropsContext />,\n },\n Heading: {\n className: styles.header,\n level: 2,\n children: dynamic((props) => header(props.children)),\n id: generatedId,\n },\n ActionGroup: {\n className: styles.actionGroup,\n spacing: \"m\",\n Action: {\n closeModal: dynamic((props) => {\n if (props.closeModal === undefined) {\n return;\n }\n if (props.closeModal === true) {\n return { bypassConfirmation: true };\n }\n return {\n bypassConfirmation: true,\n ...props.closeModal,\n };\n }),\n closeOverlay: dynamic((props) => {\n if (
|
|
1
|
+
{"version":3,"file":"Modal.mjs","names":[],"sources":["../../../../../../../src/components/Modal/Modal.tsx"],"sourcesContent":["import { type PropsWithChildren, type ReactNode, Suspense, useId } from \"react\";\nimport styles from \"./Modal.module.scss\";\nimport clsx from \"clsx\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport { OverlayController } from \"@/lib/controller/overlay\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { Overlay, type OverlayProps } from \"@/components/Overlay/Overlay\";\nimport { Action } from \"@/components/Action\";\nimport { IconClose } from \"@/components/Icon/components/icons\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport ButtonView from \"@/views/ButtonView\";\nimport DivView from \"@/views/DivView\";\nimport { OffCanvasSuspenseFallback } from \"@/components/Modal/components/OffCanvasSuspenseFallback\";\nimport { ConfirmUnsavedChangesModal } from \"@/components/Modal/components/ConfirmUnsavedChangesModal/ConfirmUnsavedChangesModal\";\nimport Wrap from \"@/components/Wrap\";\nimport { ClearPropsContext } from \"@/components/ClearPropsContext/ClearPropsContext\";\nimport ClearPropsContextView from \"@/views/ClearPropsContextView\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider\";\nimport { useVirtualKeyboardVisible } from \"@/lib/hooks/dom/useVirtualKeyboardVisible\";\nimport locales from \"./locales/*.locale.json\";\n\ntype SupportedOverlayProps = Pick<\n OverlayProps,\n \"isOpen\" | \"isDefaultOpen\" | \"onOpen\" | \"onClose\" | \"onOpenChange\"\n>;\n\nexport interface ModalProps\n extends\n PropsWithChildren,\n FlowComponentProps,\n PropsWithClassName,\n SupportedOverlayProps {\n /** The size of the modal. @default \"s\" */\n size?: \"s\" | \"m\" | \"l\";\n /** Whether the modal should be displayed as an off canvas. */\n offCanvas?: boolean;\n /**\n * Whether the off canvas should be displayed on the right or left side of the\n * screen. @default \"right\"\n */\n offCanvasOrientation?: \"left\" | \"right\";\n /** An overlay controller to control the modal state. */\n controller?: OverlayController;\n /**\n * Accepts \"actionConfirm\" to use the modal as a confirmation modal for an\n * action.\n */\n slot?: string;\n /** Whether the modal can be closed by clicking outside of it. */\n isDismissable?: boolean;\n /** Whether the close button should be visible */\n showCloseButton?: boolean;\n /**\n * Whether closing the modal must be confirmed – use it to protect unsaved\n * changes.\n */\n confirmOnClose?: boolean;\n}\n\nexport const Modal = flowComponent(\"Modal\", (props) => {\n const {\n size = \"s\",\n offCanvas,\n controller,\n children,\n ref,\n className,\n offCanvasOrientation = \"right\",\n showCloseButton,\n ...overlayProps\n } = props;\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"Modal\");\n\n // On mobile the header/footer are docked (sticky) while at rest, but flow\n // normally while the on-screen keyboard is open so the content gets the full\n // available space (see Modal.module.scss). #2423\n const keyboardVisible = useVirtualKeyboardVisible();\n\n const rootClassName = clsx(\n offCanvas ? styles.offCanvas : styles.modal,\n styles[`size-${size}`],\n offCanvasOrientation === \"left\" && styles[\"left\"],\n keyboardVisible && styles.keyboardVisible,\n className,\n );\n\n const generatedId = useId();\n\n const header = (children: ReactNode) => (\n <>\n <DivView className={styles.headerTitle}>{children}</DivView>\n <ClearPropsContext>\n <ClearPropsContextView>\n <Action closeModal={{ bypassConfirmation: true }}>\n <ButtonView\n variant=\"plain\"\n color=\"secondary\"\n aria-label={stringFormatter.format(\"close\")}\n className={clsx(\n styles.closeButton,\n showCloseButton === true\n ? styles.alwaysVisible\n : showCloseButton === false\n ? styles.alwaysHidden\n : undefined,\n )}\n >\n <IconClose />\n </ButtonView>\n </Action>\n </ClearPropsContextView>\n </ClearPropsContext>\n </>\n );\n\n const nestedHeadingLevel = 3;\n\n const nestedHeadingProps: PropsContext = {\n Heading: { level: nestedHeadingLevel },\n Section: {\n Header: { Heading: { level: nestedHeadingLevel } },\n Heading: { level: nestedHeadingLevel },\n hideSeparator: true,\n },\n Header: { Heading: { level: nestedHeadingLevel } },\n };\n\n const propsContext: PropsContext = {\n Content: {\n ...nestedHeadingProps,\n className: styles.content,\n },\n ColumnLayout: {\n ...nestedHeadingProps,\n l: [2, 1],\n m: [1],\n className: styles.columnLayout,\n AccentBox: { className: styles.accentBox, backgroundColor: \"neutral\" },\n wrapWith: <ClearPropsContext />,\n },\n Heading: {\n className: styles.header,\n level: 2,\n children: dynamic((props) => header(props.children)),\n id: generatedId,\n },\n ActionGroup: {\n className: styles.actionGroup,\n spacing: \"m\",\n Action: {\n closeModal: dynamic((props) => {\n if (props.closeModal === undefined) {\n return;\n }\n if (props.closeModal === true) {\n return { bypassConfirmation: true };\n }\n return {\n bypassConfirmation: true,\n ...props.closeModal,\n };\n }),\n closeOverlay: dynamic((props) => {\n const { closeOverlay } = props;\n if (closeOverlay === undefined || closeOverlay === false) {\n return closeOverlay;\n }\n // `true` keeps its \"the nearest overlay\" meaning by leaving `overlay`\n // unset – the options object means the same thing.\n if (closeOverlay === true) {\n return { bypassConfirmation: true };\n }\n if (\n closeOverlay instanceof OverlayController ||\n typeof closeOverlay === \"string\"\n ) {\n return {\n bypassConfirmation: true,\n overlay: closeOverlay,\n };\n }\n return {\n bypassConfirmation: true,\n ...closeOverlay,\n };\n }),\n },\n },\n };\n\n return (\n <Overlay\n className={rootClassName}\n controller={controller}\n ref={ref}\n aria-labelledby={generatedId}\n {...overlayProps}\n >\n <PropsContextProvider props={propsContext}>\n <Wrap if={offCanvas}>\n <Suspense fallback={<OffCanvasSuspenseFallback />}>\n {children}\n </Suspense>\n </Wrap>\n </PropsContextProvider>\n <ConfirmUnsavedChangesModal />\n </Overlay>\n );\n});\n\nexport default Modal;\n"],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ var OverlayTrigger = (props) => {
|
|
|
31
31
|
return /* @__PURE__ */ jsx(OverlayContextProvider, {
|
|
32
32
|
type: overlayType,
|
|
33
33
|
controller: overlayController,
|
|
34
|
+
isOverlayContent: false,
|
|
34
35
|
children: /* @__PURE__ */ jsx(PropsContextProvider, {
|
|
35
36
|
props: propsContext,
|
|
36
37
|
dependencies: [isPending, overlayController],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayTrigger.mjs","names":[],"sources":["../../../../../../../src/components/OverlayTrigger/OverlayTrigger.tsx"],"sourcesContent":["import type { ComponentType, FC, PropsWithChildren, ReactNode } from \"react\";\nimport { OverlayController } from \"@/lib/controller\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport { useComponentPropsContext } from \"@/lib/propsContext/propsContext\";\nimport type { FlowComponentName } from \"@/components/propTypes\";\nimport OverlayContextProvider from \"@/lib/controller/overlay/OverlayContextProvider\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { useIsPendingWithWait } from \"@/components/Action/hooks/useIsPendingWithWait\";\n\ntype AriaComponentType = ComponentType<{\n isOpen?: boolean;\n children: ReactNode;\n}>;\n\nexport interface OverlayTriggerProps\n extends FlowComponentProps, PropsWithChildren {\n /** Whether the overlay should be open initially. */\n isDefaultOpen?: boolean;\n /** A controller to control the state of the overlay. */\n controller?: OverlayController;\n}\n\ninterface Props extends OverlayTriggerProps {\n overlayType: FlowComponentName;\n component: AriaComponentType;\n}\n\nexport const OverlayTrigger: FC<Props> = (props) => {\n const {\n overlayType,\n isDefaultOpen = false,\n component: AriaOverlayTrigger,\n children,\n controller: controllerFromProps,\n } = props;\n const buttonPropsContext = useComponentPropsContext(\"Button\");\n\n const newOverlayController = OverlayController.useNew({ isDefaultOpen });\n const overlayController = controllerFromProps ?? newOverlayController;\n const isOpen = overlayController.useIsOpen();\n const isContentSuspended = overlayController.useIsContentSuspended();\n const isPending = useIsPendingWithWait(isContentSuspended);\n\n const propsContext: PropsContext = {\n Button: {\n onPress: overlayController.open,\n isPending,\n isDisabled: Boolean(buttonPropsContext?.isDisabled) || isContentSuspended,\n /*\n * The button is the react-aria trigger. react-aria hands the press\n * handling, the trigger ref and `aria-haspopup`/`aria-expanded`/\n * `aria-controls` down through a `PressResponder`, which only reaches its\n * own subtree — so a surrounding props context must not tunnel the button\n * out of the trigger. Such a context has to tunnel the trigger as a whole\n * instead (`overlayTriggersTunneledTo`).\n */\n tunnel: null,\n },\n /*\n * The aria trigger this renders is the host-side identity of every trigger\n * that is not `@flr-generate` (see `overlayTriggersTunneledTo`), so a\n * tunneling props context targets it as well. Here it is already inside the\n * trigger the author wrote — tunneling it again would send the same subtree\n * into the exit twice.\n */\n DialogTrigger: {\n tunnel: null,\n },\n /*\n * The overlay is already placed — this trigger owns it. A surrounding\n * props context that moves or wraps the bare overlay, so that it can be\n * written without a trigger (`Badge`), must not reach this one: it would\n * pull the overlay out of its trigger and add a second trigger button\n * around it.\n */\n [overlayType]: {\n tunnel: null,\n wrapWith: null,\n },\n };\n\n return (\n <OverlayContextProvider
|
|
1
|
+
{"version":3,"file":"OverlayTrigger.mjs","names":[],"sources":["../../../../../../../src/components/OverlayTrigger/OverlayTrigger.tsx"],"sourcesContent":["import type { ComponentType, FC, PropsWithChildren, ReactNode } from \"react\";\nimport { OverlayController } from \"@/lib/controller\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\nimport { useComponentPropsContext } from \"@/lib/propsContext/propsContext\";\nimport type { FlowComponentName } from \"@/components/propTypes\";\nimport OverlayContextProvider from \"@/lib/controller/overlay/OverlayContextProvider\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { useIsPendingWithWait } from \"@/components/Action/hooks/useIsPendingWithWait\";\n\ntype AriaComponentType = ComponentType<{\n isOpen?: boolean;\n children: ReactNode;\n}>;\n\nexport interface OverlayTriggerProps\n extends FlowComponentProps, PropsWithChildren {\n /** Whether the overlay should be open initially. */\n isDefaultOpen?: boolean;\n /** A controller to control the state of the overlay. */\n controller?: OverlayController;\n}\n\ninterface Props extends OverlayTriggerProps {\n overlayType: FlowComponentName;\n component: AriaComponentType;\n}\n\nexport const OverlayTrigger: FC<Props> = (props) => {\n const {\n overlayType,\n isDefaultOpen = false,\n component: AriaOverlayTrigger,\n children,\n controller: controllerFromProps,\n } = props;\n const buttonPropsContext = useComponentPropsContext(\"Button\");\n\n const newOverlayController = OverlayController.useNew({ isDefaultOpen });\n const overlayController = controllerFromProps ?? newOverlayController;\n const isOpen = overlayController.useIsOpen();\n const isContentSuspended = overlayController.useIsContentSuspended();\n const isPending = useIsPendingWithWait(isContentSuspended);\n\n const propsContext: PropsContext = {\n Button: {\n onPress: overlayController.open,\n isPending,\n isDisabled: Boolean(buttonPropsContext?.isDisabled) || isContentSuspended,\n /*\n * The button is the react-aria trigger. react-aria hands the press\n * handling, the trigger ref and `aria-haspopup`/`aria-expanded`/\n * `aria-controls` down through a `PressResponder`, which only reaches its\n * own subtree — so a surrounding props context must not tunnel the button\n * out of the trigger. Such a context has to tunnel the trigger as a whole\n * instead (`overlayTriggersTunneledTo`).\n */\n tunnel: null,\n },\n /*\n * The aria trigger this renders is the host-side identity of every trigger\n * that is not `@flr-generate` (see `overlayTriggersTunneledTo`), so a\n * tunneling props context targets it as well. Here it is already inside the\n * trigger the author wrote — tunneling it again would send the same subtree\n * into the exit twice.\n */\n DialogTrigger: {\n tunnel: null,\n },\n /*\n * The overlay is already placed — this trigger owns it. A surrounding\n * props context that moves or wraps the bare overlay, so that it can be\n * written without a trigger (`Badge`), must not reach this one: it would\n * pull the overlay out of its trigger and add a second trigger button\n * around it.\n */\n [overlayType]: {\n tunnel: null,\n wrapWith: null,\n },\n };\n\n return (\n <OverlayContextProvider\n type={overlayType}\n controller={overlayController}\n isOverlayContent={false}\n >\n <PropsContextProvider\n props={propsContext}\n dependencies={[isPending, overlayController]}\n >\n <AriaOverlayTrigger isOpen={isOpen}>{children}</AriaOverlayTrigger>\n </PropsContextProvider>\n </OverlayContextProvider>\n );\n};\n\nexport default OverlayTrigger;\n"],"mappings":";;;;;;;;;AA4BA,IAAa,kBAA6B,UAAU;CAClD,MAAM,EACJ,aACA,gBAAgB,OAChB,WAAW,oBACX,UACA,YAAY,wBACV;CACJ,MAAM,qBAAqB,yBAAyB,QAAQ;CAE5D,MAAM,uBAAuB,kBAAkB,OAAO,EAAE,cAAc,CAAC;CACvE,MAAM,oBAAoB,uBAAuB;CACjD,MAAM,SAAS,kBAAkB,UAAU;CAC3C,MAAM,qBAAqB,kBAAkB,sBAAsB;CACnE,MAAM,YAAY,qBAAqB,kBAAkB;CAEzD,MAAM,eAA6B;EACjC,QAAQ;GACN,SAAS,kBAAkB;GAC3B;GACA,YAAY,QAAQ,oBAAoB,UAAU,KAAK;GASvD,QAAQ;EACV;EAQA,eAAe,EACb,QAAQ,KACV;GAQC,cAAc;GACb,QAAQ;GACR,UAAU;EACZ;CACF;CAEA,OACE,oBAAC,wBAAD;EACE,MAAM;EACN,YAAY;EACZ,kBAAkB;EAElB,UAAA,oBAAC,sBAAD;GACE,OAAO;GACP,cAAc,CAAC,WAAW,iBAAiB;GAE3C,UAAA,oBAAC,oBAAD;IAA4B;IAAS;GAA6B,CAAA;EAC9C,CAAA;CACA,CAAA;AAE5B"}
|
package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs
CHANGED
|
@@ -21,6 +21,7 @@ import { TogglePasswordVisibilityButton } from "./components/TogglePasswordVisib
|
|
|
21
21
|
import { ValidationResultButton } from "./components/ValidationResultButton/ValidationResultButton.mjs";
|
|
22
22
|
import { PasswordGenerateButton } from "./components/PasswordGenerateButton/PasswordGenerateButton.mjs";
|
|
23
23
|
import { usePolicyValidationResult } from "./lib/usePolicyValidationResult.mjs";
|
|
24
|
+
import { useAriaAnnouncePasswordVisibility, useAriaAnnounceValidationState } from "./lib/ariaAnnounce.mjs";
|
|
24
25
|
import clsx from "clsx";
|
|
25
26
|
import { useMemo, useRef, useState } from "react";
|
|
26
27
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -29,7 +30,6 @@ import * as Aria from "react-aria-components";
|
|
|
29
30
|
/** @flr-generate all */
|
|
30
31
|
var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
31
32
|
const { children, className, ref, isDisabled, onValidationResult, isInvalid: invalidFromProps, validationPolicy: validationPolicyFromProps = defaultPasswordCreationPolicy, isRequired, value, onChange, ...rest } = useControlledHostValueProps(props, "");
|
|
32
|
-
const { FieldErrorView, FieldErrorCaptureContext, fieldProps, fieldPropsContext } = useFieldComponent(props, "PasswordCreationField");
|
|
33
33
|
const translate = useLocalizedStringFormatter(__locale_default, "PasswordCreationField");
|
|
34
34
|
const validationPolicy = useMemo(() => Policy.fromDeclaration(validationPolicyFromProps), [validationPolicyFromProps]);
|
|
35
35
|
const [isPasswordRevealed, setIsPasswordRevealed] = useState(false);
|
|
@@ -77,6 +77,12 @@ 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, fieldProps, fieldPropsContext } = useFieldComponent({
|
|
81
|
+
...props,
|
|
82
|
+
isInvalid
|
|
83
|
+
}, "PasswordCreationField");
|
|
84
|
+
useAriaAnnounceValidationState(latestValidationErrorText, !isEmptyValue && policyValidationResult.isValid !== "indeterminate");
|
|
85
|
+
useAriaAnnouncePasswordVisibility(isPasswordRevealed);
|
|
80
86
|
const setOptimisticPolicyValidationResult = (state = {}) => {
|
|
81
87
|
setPolicyValidationResult((currentState) => ({
|
|
82
88
|
...currentState,
|
|
@@ -149,6 +155,7 @@ var PasswordCreationField = flowComponent("PasswordCreationField", (props) => {
|
|
|
149
155
|
};
|
|
150
156
|
return /* @__PURE__ */ jsxs(Aria.TextField, {
|
|
151
157
|
...rest,
|
|
158
|
+
...fieldProps,
|
|
152
159
|
value,
|
|
153
160
|
type: isPasswordRevealed ? "text" : "password",
|
|
154
161
|
onChange,
|
|
@@ -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\";\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 {\n FieldErrorView,\n FieldErrorCaptureContext,\n fieldProps,\n fieldPropsContext,\n } = useFieldComponent(props, \"PasswordCreationField\");\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 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 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":"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"}
|
|
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":"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"}
|
|
@@ -7,6 +7,7 @@ import __locale_default from "../../../../../../../_virtual/_28.locale.mjs";
|
|
|
7
7
|
import "react";
|
|
8
8
|
import { jsx } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton.tsx
|
|
10
|
+
/** @internal */
|
|
10
11
|
var PasswordGenerateButton = (props) => {
|
|
11
12
|
const { isDisabled, onGeneratePasswordAction } = props;
|
|
12
13
|
const translate = useLocalizedStringFormatter(__locale_default, "PasswordCreationField");
|
|
@@ -18,6 +19,7 @@ var PasswordGenerateButton = (props) => {
|
|
|
18
19
|
isDisabled,
|
|
19
20
|
variant: "plain",
|
|
20
21
|
color: "secondary",
|
|
22
|
+
"aria-label": translate.format("button.generate.label"),
|
|
21
23
|
children: translate.format("button.generate")
|
|
22
24
|
})
|
|
23
25
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordGenerateButton.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton.tsx"],"sourcesContent":["import { type FC } from \"react\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./../../locales/*.locale.json\";\nimport { Button } from \"@/components/Button\";\nimport { Action, type ActionFn } from \"@/components/Action\";\n\ninterface Props {\n isDisabled?: boolean;\n onGeneratePasswordAction?: ActionFn;\n}\n\nexport const PasswordGenerateButton: FC<Props> = (props) => {\n const { isDisabled, onGeneratePasswordAction } = props;\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n return (\n <Action onAction={onGeneratePasswordAction} showFeedback={false}>\n <Button\n data-component=\"generatePassword\"\n isDisabled={isDisabled}\n variant=\"plain\"\n color=\"secondary\"\n >\n {translate.format(\"button.generate\")}\n </Button>\n </Action>\n );\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PasswordGenerateButton.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/PasswordGenerateButton/PasswordGenerateButton.tsx"],"sourcesContent":["import { type FC } from \"react\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./../../locales/*.locale.json\";\nimport { Button } from \"@/components/Button\";\nimport { Action, type ActionFn } from \"@/components/Action\";\n\ninterface Props {\n isDisabled?: boolean;\n onGeneratePasswordAction?: ActionFn;\n}\n\n/** @internal */\nexport const PasswordGenerateButton: FC<Props> = (props) => {\n const { isDisabled, onGeneratePasswordAction } = props;\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n return (\n <Action onAction={onGeneratePasswordAction} showFeedback={false}>\n <Button\n data-component=\"generatePassword\"\n isDisabled={isDisabled}\n variant=\"plain\"\n color=\"secondary\"\n // The button sits in the label, where \"Generate\" alone does not say\n // what is generated.\n aria-label={translate.format(\"button.generate.label\")}\n >\n {translate.format(\"button.generate\")}\n </Button>\n </Action>\n );\n};\n"],"mappings":";;;;;;;;;;AAYA,IAAa,0BAAqC,UAAU;CAC1D,MAAM,EAAE,YAAY,6BAA6B;CACjD,MAAM,YAAY,4BAChB,kBACA,uBACF;CAEA,OACE,oBAAC,QAAD;EAAQ,UAAU;EAA0B,cAAc;EACxD,UAAA,oBAAC,QAAD;GACE,kBAAe;GACH;GACZ,SAAQ;GACR,OAAM;GAGN,cAAY,UAAU,OAAO,uBAAuB;GAEnD,UAAA,UAAU,OAAO,iBAAiB;EAC7B,CAAA;CACF,CAAA;AAEZ"}
|
|
@@ -7,12 +7,15 @@ import { Heading } from "../../../Heading/Heading.mjs";
|
|
|
7
7
|
import { ContextualHelp } from "../../../ContextualHelp/ContextualHelp.mjs";
|
|
8
8
|
import __locale_default from "../../../../../../../_virtual/_28.locale.mjs";
|
|
9
9
|
import { ValidationResultEntry } from "../ValidationResultEntry/ValidationResultEntry.mjs";
|
|
10
|
-
import "
|
|
10
|
+
import ValidationResultButton_module_default from "./ValidationResultButton.module.mjs";
|
|
11
|
+
import { useId } from "react";
|
|
11
12
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
13
|
//#region src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.tsx
|
|
14
|
+
/** @internal */
|
|
13
15
|
var ValidationResultButton = (props) => {
|
|
14
16
|
const { policyValidationResult, isDisabled, isEmptyValue, className } = props;
|
|
15
17
|
const translate = useLocalizedStringFormatter(__locale_default, "PasswordCreationField");
|
|
18
|
+
const headingId = useId();
|
|
16
19
|
let validationResults = policyValidationResult?.ruleResults?.filter((r) => {
|
|
17
20
|
return isEmptyValue ? !r.isValid : true;
|
|
18
21
|
});
|
|
@@ -26,14 +29,17 @@ var ValidationResultButton = (props) => {
|
|
|
26
29
|
"data-component": "showPasswordRules",
|
|
27
30
|
isDisabled,
|
|
28
31
|
className
|
|
29
|
-
}), /* @__PURE__ */ jsxs(ContextualHelp, { children: [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
}), /* @__PURE__ */ jsxs(ContextualHelp, { children: [/* @__PURE__ */ jsx(Heading, {
|
|
33
|
+
id: headingId,
|
|
34
|
+
children: translate.format("password.requirements.heading")
|
|
35
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
36
|
+
"aria-labelledby": headingId,
|
|
37
|
+
className: ValidationResultButton_module_default.validationResultList,
|
|
38
|
+
children: validationResultComponents.length === 0 ? /* @__PURE__ */ jsx(ValidationResultEntry, {
|
|
32
39
|
result: { isValid: true },
|
|
33
40
|
unspecifiedRules: true
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
] })]
|
|
41
|
+
}) : validationResultComponents
|
|
42
|
+
})] })]
|
|
37
43
|
});
|
|
38
44
|
};
|
|
39
45
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationResultButton.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.tsx"],"sourcesContent":["import { type FC } from \"react\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\n\nimport locales from \"./../../locales/*.locale.json\";\nimport type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport ValidationResultEntry from \"@/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry\";\nimport { Button } from \"@/components/Button\";\nimport {\n ContextualHelp,\n ContextualHelpTrigger,\n} from \"@/components/ContextualHelp\";\nimport { Heading } from \"@/components/Heading\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\n\ninterface Props extends PropsWithClassName {\n policyValidationResult?: ResolvedPolicyValidationResult;\n isDisabled?: boolean;\n isEmptyValue: boolean;\n}\n\nexport const ValidationResultButton: FC<Props> = (props) => {\n const { policyValidationResult, isDisabled, isEmptyValue, className } = props;\n\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n let validationResults = policyValidationResult?.ruleResults?.filter((r) => {\n return isEmptyValue ? !r.isValid : true;\n });\n if (validationResults && validationResults.length === 0 && isEmptyValue) {\n // if we have no rules to show on first info - just list them all\n validationResults = policyValidationResult?.ruleResults;\n }\n\n const validationResultComponents =\n validationResults?.map((result, index) => {\n return (\n <ValidationResultEntry\n key={`${result.identifier}-${index}`}\n result={result}\n />\n );\n }) ?? [];\n\n return (\n <ContextualHelpTrigger\n subject={translate.format(\"password.requirements.subject\")}\n >\n <Button\n data-component=\"showPasswordRules\"\n isDisabled={isDisabled}\n className={className}\n />\n <ContextualHelp>\n <Heading
|
|
1
|
+
{"version":3,"file":"ValidationResultButton.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.tsx"],"sourcesContent":["import { type FC, useId } from \"react\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\n\nimport locales from \"./../../locales/*.locale.json\";\nimport type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport ValidationResultEntry from \"@/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry\";\nimport { Button } from \"@/components/Button\";\nimport {\n ContextualHelp,\n ContextualHelpTrigger,\n} from \"@/components/ContextualHelp\";\nimport { Heading } from \"@/components/Heading\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport styles from \"./ValidationResultButton.module.scss\";\n\ninterface Props extends PropsWithClassName {\n policyValidationResult?: ResolvedPolicyValidationResult;\n isDisabled?: boolean;\n isEmptyValue: boolean;\n}\n\n/** @internal */\nexport const ValidationResultButton: FC<Props> = (props) => {\n const { policyValidationResult, isDisabled, isEmptyValue, className } = props;\n\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n const headingId = useId();\n\n let validationResults = policyValidationResult?.ruleResults?.filter((r) => {\n return isEmptyValue ? !r.isValid : true;\n });\n if (validationResults && validationResults.length === 0 && isEmptyValue) {\n // if we have no rules to show on first info - just list them all\n validationResults = policyValidationResult?.ruleResults;\n }\n\n const validationResultComponents =\n validationResults?.map((result, index) => {\n return (\n <ValidationResultEntry\n key={`${result.identifier}-${index}`}\n result={result}\n />\n );\n }) ?? [];\n\n return (\n <ContextualHelpTrigger\n subject={translate.format(\"password.requirements.subject\")}\n >\n <Button\n data-component=\"showPasswordRules\"\n isDisabled={isDisabled}\n className={className}\n />\n <ContextualHelp>\n <Heading id={headingId}>\n {translate.format(\"password.requirements.heading\")}\n </Heading>\n {/* A list, so a screen reader announces the requirements as one unit\n with their number — and each rule with its status. */}\n <ul aria-labelledby={headingId} className={styles.validationResultList}>\n {validationResultComponents.length === 0 ? (\n <ValidationResultEntry\n result={{ isValid: true }}\n unspecifiedRules\n />\n ) : (\n validationResultComponents\n )}\n </ul>\n </ContextualHelp>\n </ContextualHelpTrigger>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAsBA,IAAa,0BAAqC,UAAU;CAC1D,MAAM,EAAE,wBAAwB,YAAY,cAAc,cAAc;CAExE,MAAM,YAAY,4BAChB,kBACA,uBACF;CACA,MAAM,YAAY,MAAM;CAExB,IAAI,oBAAoB,wBAAwB,aAAa,QAAQ,MAAM;EACzE,OAAO,eAAe,CAAC,EAAE,UAAU;CACrC,CAAC;CACD,IAAI,qBAAqB,kBAAkB,WAAW,KAAK,cAEzD,oBAAoB,wBAAwB;CAG9C,MAAM,6BACJ,mBAAmB,KAAK,QAAQ,UAAU;EACxC,OACE,oBAAC,uBAAD,EAEU,OACT,GAFM,GAAG,OAAO,WAAW,GAAG,OAE9B;CAEL,CAAC,KAAK,CAAC;CAET,OACE,qBAAC,uBAAD;EACE,SAAS,UAAU,OAAO,+BAA+B;EAD3D,UAAA,CAGE,oBAAC,QAAD;GACE,kBAAe;GACH;GACD;EACZ,CAAA,GACD,qBAAC,gBAAD,EAAA,UAAA,CACE,oBAAC,SAAD;GAAS,IAAI;GACV,UAAA,UAAU,OAAO,+BAA+B;EAC1C,CAAA,GAGT,oBAAC,MAAD;GAAI,mBAAiB;GAAW,WAAW,sCAAO;GAC/C,UAAA,2BAA2B,WAAW,IACrC,oBAAC,uBAAD;IACE,QAAQ,EAAE,SAAS,KAAK;IACxB,kBAAA;GACD,CAAA,IAED;EAEA,CAAA,CACU,EAAA,CAAA,CACK;;AAE3B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
/* */
|
|
3
|
+
//#region src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.module.scss
|
|
4
|
+
var validationResultList = "flow--password-creation-field--validation-result-button--validation-result-list";
|
|
5
|
+
var ValidationResultButton_module_default = { validationResultList };
|
|
6
|
+
//#endregion
|
|
7
|
+
export { ValidationResultButton_module_default as default, validationResultList };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=ValidationResultButton.module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationResultButton.module.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.module.scss"],"sourcesContent":[".validationResultList {\n display: flex;\n flex-direction: column;\n row-gap: var(--password-creation-field--rule-to-rule-spacing);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n"],"mappings":""}
|
|
@@ -7,23 +7,31 @@ import __locale_default from "../../../../../../../_virtual/_28.locale.mjs";
|
|
|
7
7
|
import generateValidationTranslation from "../../lib/generateValidationTranslation.mjs";
|
|
8
8
|
import ValidationResultEntry_module_default from "./ValidationResultEntry.module.mjs";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import * as Aria from "react-aria-components";
|
|
10
11
|
//#region src/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry.tsx
|
|
11
12
|
/** @internal */
|
|
12
13
|
var ValidationResultEntry = (props) => {
|
|
13
14
|
const { result, unspecifiedRules = false } = props;
|
|
14
15
|
const translate = useLocalizedStringFormatter(__locale_default, "PasswordCreationField");
|
|
15
|
-
const icon = /* @__PURE__ */ jsx(AlertIcon, {
|
|
16
|
+
const icon = /* @__PURE__ */ jsx(AlertIcon, {
|
|
17
|
+
status: result.isValid ? "success" : "warning",
|
|
18
|
+
"aria-label": void 0
|
|
19
|
+
});
|
|
20
|
+
const status = translate.format(result.isValid ? "password.requirements.rule.fulfilled" : "password.requirements.rule.unfulfilled");
|
|
16
21
|
let [translationKey, translationValues] = generateValidationTranslation(result, true);
|
|
17
22
|
if (unspecifiedRules) {
|
|
18
23
|
translationKey = `${translationKey}.unspecified`;
|
|
19
24
|
translationValues = {};
|
|
20
25
|
}
|
|
21
|
-
return /* @__PURE__ */ jsxs(
|
|
26
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
22
27
|
className: ValidationResultEntry_module_default.validationResultEntry,
|
|
23
28
|
"data-rule": result.ruleType,
|
|
24
29
|
"data-rule-valid": result.isValid,
|
|
25
|
-
children: [icon,
|
|
26
|
-
|
|
30
|
+
children: [icon, /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Aria.VisuallyHidden, {
|
|
31
|
+
elementType: "span",
|
|
32
|
+
children: `${status}: `
|
|
33
|
+
}), translate.format(translationKey, translationValues)] })]
|
|
34
|
+
});
|
|
27
35
|
};
|
|
28
36
|
//#endregion
|
|
29
37
|
export { ValidationResultEntry, ValidationResultEntry as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationResultEntry.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { Text } from \"@/components/Text\";\nimport generateValidationTranslation from \"@/components/PasswordCreationField/lib/generateValidationTranslation\";\nimport locales from \"./../../locales/*.locale.json\";\nimport styles from \"./ValidationResultEntry.module.scss\";\nimport type { RuleValidationResult } from \"@/integrations/@mittwald/password-tools-js\";\nimport AlertIcon from \"@/components/AlertIcon\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\n\ninterface Props {\n result: Partial<RuleValidationResult>;\n unspecifiedRules?: boolean;\n}\n\n/** @internal */\nexport const ValidationResultEntry: FC<Props> = (props) => {\n const { result, unspecifiedRules = false } = props;\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n const icon = <AlertIcon
|
|
1
|
+
{"version":3,"file":"ValidationResultEntry.mjs","names":[],"sources":["../../../../../../../../../src/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport { Text } from \"@/components/Text\";\nimport generateValidationTranslation from \"@/components/PasswordCreationField/lib/generateValidationTranslation\";\nimport locales from \"./../../locales/*.locale.json\";\nimport styles from \"./ValidationResultEntry.module.scss\";\nimport type { RuleValidationResult } from \"@/integrations/@mittwald/password-tools-js\";\nimport AlertIcon from \"@/components/AlertIcon\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\n\ninterface Props {\n result: Partial<RuleValidationResult>;\n unspecifiedRules?: boolean;\n}\n\n/** @internal */\nexport const ValidationResultEntry: FC<Props> = (props) => {\n const { result, unspecifiedRules = false } = props;\n const translate = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n\n const icon = (\n <AlertIcon\n status={result.isValid ? \"success\" : \"warning\"}\n // The status is spelled out as text right next to it, so the icon is\n // decorative. Overriding `AlertIcon`'s generic \"Status …\" label with\n // `undefined` is what makes `Icon` hide it from the accessibility tree.\n aria-label={undefined}\n />\n );\n\n const status = translate.format(\n result.isValid\n ? \"password.requirements.rule.fulfilled\"\n : \"password.requirements.rule.unfulfilled\",\n );\n\n let [translationKey, translationValues] = generateValidationTranslation(\n result,\n true,\n );\n\n if (unspecifiedRules) {\n translationKey = `${translationKey}.unspecified`;\n translationValues = {};\n }\n\n return (\n <li\n className={styles.validationResultEntry}\n data-rule={result.ruleType}\n data-rule-valid={result.isValid}\n >\n {icon}\n <Text>\n <Aria.VisuallyHidden elementType=\"span\">{`${status}: `}</Aria.VisuallyHidden>\n {translate.format(translationKey, translationValues)}\n </Text>\n </li>\n );\n};\n\nexport default ValidationResultEntry;\n"],"mappings":";;;;;;;;;;;;AAgBA,IAAa,yBAAoC,UAAU;CACzD,MAAM,EAAE,QAAQ,mBAAmB,UAAU;CAC7C,MAAM,YAAY,4BAChB,kBACA,uBACF;CAEA,MAAM,OACJ,oBAAC,WAAD;EACE,QAAQ,OAAO,UAAU,YAAY;EAIrC,cAAY,KAAA;CACb,CAAA;CAGH,MAAM,SAAS,UAAU,OACvB,OAAO,UACH,yCACA,wCACN;CAEA,IAAI,CAAC,gBAAgB,qBAAqB,8BACxC,QACA,IACF;CAEA,IAAI,kBAAkB;EACpB,iBAAiB,GAAG,eAAe;EACnC,oBAAoB,CAAC;CACvB;CAEA,OACE,qBAAC,MAAD;EACE,WAAW,qCAAO;EAClB,aAAW,OAAO;EAClB,mBAAiB,OAAO;EAH1B,UAAA,CAKG,MACD,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,KAAK,gBAAN;GAAqB,aAAY;GAAQ,UAAA,GAAG,OAAO;EAAyB,CAAA,GAC3E,UAAU,OAAO,gBAAgB,iBAAiB,CAC/C,EAAA,CAAA,CACJ;;AAER"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
/* */
|
|
3
|
+
import { useLocalizedStringFormatter } from "../../TranslationProvider/useLocalizedStringFormatter.mjs";
|
|
4
|
+
import __locale_default from "../../../../../../_virtual/_28.locale.mjs";
|
|
5
|
+
import { useEffect, useRef } from "react";
|
|
6
|
+
import { announce } from "@react-aria/live-announcer";
|
|
7
|
+
//#region src/components/PasswordCreationField/lib/ariaAnnounce.ts
|
|
8
|
+
/**
|
|
9
|
+
* Announces the current validation message — which rule the password misses, or
|
|
10
|
+
* that it is secure.
|
|
11
|
+
*
|
|
12
|
+
* The same text is wired to the field via `aria-describedby`, but a description
|
|
13
|
+
* is only read when the field receives focus. The field keeps focus while the
|
|
14
|
+
* password is typed, so without a live region a screen reader reports the field
|
|
15
|
+
* as invalid and never says why.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
var useAriaAnnounceValidationState = (text, isAnnounceable) => {
|
|
20
|
+
const lastAnnouncedText = useRef(void 0);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!isAnnounceable || !text) {
|
|
23
|
+
lastAnnouncedText.current = void 0;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (text === lastAnnouncedText.current) return;
|
|
27
|
+
lastAnnouncedText.current = text;
|
|
28
|
+
announce(text, "polite");
|
|
29
|
+
}, [text, isAnnounceable]);
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Announces that the password became visible or hidden. The toggle button keeps
|
|
33
|
+
* focus, and a screen reader does not report that the input switched between
|
|
34
|
+
* masked characters and plain text on its own.
|
|
35
|
+
*
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
var useAriaAnnouncePasswordVisibility = (isRevealed) => {
|
|
39
|
+
const formatter = useLocalizedStringFormatter(__locale_default, "PasswordCreationField");
|
|
40
|
+
const isInitialRender = useRef(true);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (isInitialRender.current) {
|
|
43
|
+
isInitialRender.current = false;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
announce(formatter.format(isRevealed ? "password.announce.revealed" : "password.announce.hidden"), "polite");
|
|
47
|
+
}, [isRevealed]);
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { useAriaAnnouncePasswordVisibility, useAriaAnnounceValidationState };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=ariaAnnounce.mjs.map
|
package/dist/js/packages/components/src/components/PasswordCreationField/lib/ariaAnnounce.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ariaAnnounce.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/ariaAnnounce.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { announce } from \"@react-aria/live-announcer\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider/useLocalizedStringFormatter\";\nimport locales from \"./../locales/*.locale.json\";\n\n/**\n * Announces the current validation message — which rule the password misses, or\n * that it is secure.\n *\n * The same text is wired to the field via `aria-describedby`, but a description\n * is only read when the field receives focus. The field keeps focus while the\n * password is typed, so without a live region a screen reader reports the field\n * as invalid and never says why.\n *\n * @internal\n */\nexport const useAriaAnnounceValidationState = (\n text: string | undefined,\n isAnnounceable: boolean,\n): void => {\n const lastAnnouncedText = useRef<string>(undefined);\n\n useEffect(() => {\n if (!isAnnounceable || !text) {\n // Announce the text again when it comes back after an empty field or a\n // pending validation.\n lastAnnouncedText.current = undefined;\n return;\n }\n\n if (text === lastAnnouncedText.current) {\n return;\n }\n\n lastAnnouncedText.current = text;\n announce(text, \"polite\");\n }, [text, isAnnounceable]);\n};\n\n/**\n * Announces that the password became visible or hidden. The toggle button keeps\n * focus, and a screen reader does not report that the input switched between\n * masked characters and plain text on its own.\n *\n * @internal\n */\nexport const useAriaAnnouncePasswordVisibility = (\n isRevealed: boolean,\n): void => {\n const formatter = useLocalizedStringFormatter(\n locales,\n \"PasswordCreationField\",\n );\n const isInitialRender = useRef(true);\n\n useEffect(() => {\n if (isInitialRender.current) {\n isInitialRender.current = false;\n return;\n }\n\n announce(\n formatter.format(\n isRevealed ? \"password.announce.revealed\" : \"password.announce.hidden\",\n ),\n \"polite\",\n );\n }, [isRevealed]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgBA,IAAa,kCACX,MACA,mBACS;CACT,MAAM,oBAAoB,OAAe,KAAA,CAAS;CAElD,gBAAgB;EACd,IAAI,CAAC,kBAAkB,CAAC,MAAM;GAG5B,kBAAkB,UAAU,KAAA;GAC5B;EACF;EAEA,IAAI,SAAS,kBAAkB,SAC7B;EAGF,kBAAkB,UAAU;EAC5B,SAAS,MAAM,QAAQ;CACzB,GAAG,CAAC,MAAM,cAAc,CAAC;AAC3B;;;;;;;;AASA,IAAa,qCACX,eACS;CACT,MAAM,YAAY,4BAChB,kBACA,uBACF;CACA,MAAM,kBAAkB,OAAO,IAAI;CAEnC,gBAAgB;EACd,IAAI,gBAAgB,SAAS;GAC3B,gBAAgB,UAAU;GAC1B;EACF;EAEA,SACE,UAAU,OACR,aAAa,+BAA+B,0BAC9C,GACA,QACF;CACF,GAAG,CAAC,UAAU,CAAC;AACjB"}
|
|
@@ -14,6 +14,7 @@ var generateTranslationString = (rule, shortVersion = false) => {
|
|
|
14
14
|
else finalTranslationString = translateString;
|
|
15
15
|
return shortVersion ? `${finalTranslationString}.short` : finalTranslationString;
|
|
16
16
|
};
|
|
17
|
+
/** @internal */
|
|
17
18
|
var generateValidationTranslation = (r, shotVersion = false) => {
|
|
18
19
|
const translationKey = generateTranslationString(r, shotVersion);
|
|
19
20
|
if (r.ruleType === RuleType.char && r.chars) return [translationKey, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateValidationTranslation.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/generateValidationTranslation.ts"],"sourcesContent":["import {\n RuleType,\n type RuleValidationResult,\n} from \"@/integrations/@mittwald/password-tools-js\";\n\nconst generateTranslationString = (\n rule: Partial<RuleValidationResult> & { translationKey?: string },\n shortVersion = false,\n): string => {\n if (rule.translationKey) {\n return `validation.${rule.translationKey}`;\n }\n const translateString = `validation.${rule.ruleType ?? \"general\"}`;\n let finalTranslationString: string;\n\n if (\n (\"min\" in rule && rule.min !== undefined) ||\n (\"max\" in rule && rule.max !== undefined)\n ) {\n const breakingBoundaryProperty = rule.failingBoundary\n ? rule.failingBoundary\n : rule.min\n ? \"min\"\n : \"max\";\n\n if (rule.identifier) {\n finalTranslationString = `${translateString}.${rule.identifier}.${breakingBoundaryProperty}`;\n } else {\n finalTranslationString = `${translateString}.${breakingBoundaryProperty}`;\n }\n } else if (rule.identifier) {\n finalTranslationString = `${translateString}.${rule.identifier}`;\n } else {\n finalTranslationString = translateString;\n }\n\n return shortVersion\n ? `${finalTranslationString}.short`\n : finalTranslationString;\n};\n\nexport const generateValidationTranslation = (\n r: Partial<RuleValidationResult>,\n shotVersion = false,\n): [string, Record<string, string | number | boolean> | undefined] => {\n const translationKey = generateTranslationString(r, shotVersion);\n\n if (r.ruleType === RuleType.char && r.chars) {\n return [\n translationKey,\n { ...r, chars: r.chars.map((c) => c.char).join(\"\") },\n ];\n }\n\n return [\n translationKey,\n r as unknown as Record<string, string | number | boolean> | undefined,\n ];\n};\n\nexport default generateValidationTranslation;\n"],"mappings":";;;;AAKA,IAAM,6BACJ,MACA,eAAe,UACJ;CACX,IAAI,KAAK,gBACP,OAAO,cAAc,KAAK;CAE5B,MAAM,kBAAkB,cAAc,KAAK,YAAY;CACvD,IAAI;CAEJ,IACG,SAAS,QAAQ,KAAK,QAAQ,KAAA,KAC9B,SAAS,QAAQ,KAAK,QAAQ,KAAA,GAC/B;EACA,MAAM,2BAA2B,KAAK,kBAClC,KAAK,kBACL,KAAK,MACH,QACA;EAEN,IAAI,KAAK,YACP,yBAAyB,GAAG,gBAAgB,GAAG,KAAK,WAAW,GAAG;OAElE,yBAAyB,GAAG,gBAAgB,GAAG;CAEnD,OAAO,IAAI,KAAK,YACd,yBAAyB,GAAG,gBAAgB,GAAG,KAAK;MAEpD,yBAAyB;CAG3B,OAAO,eACH,GAAG,uBAAuB,UAC1B;AACN
|
|
1
|
+
{"version":3,"file":"generateValidationTranslation.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/generateValidationTranslation.ts"],"sourcesContent":["import {\n RuleType,\n type RuleValidationResult,\n} from \"@/integrations/@mittwald/password-tools-js\";\n\nconst generateTranslationString = (\n rule: Partial<RuleValidationResult> & { translationKey?: string },\n shortVersion = false,\n): string => {\n if (rule.translationKey) {\n return `validation.${rule.translationKey}`;\n }\n const translateString = `validation.${rule.ruleType ?? \"general\"}`;\n let finalTranslationString: string;\n\n if (\n (\"min\" in rule && rule.min !== undefined) ||\n (\"max\" in rule && rule.max !== undefined)\n ) {\n const breakingBoundaryProperty = rule.failingBoundary\n ? rule.failingBoundary\n : rule.min\n ? \"min\"\n : \"max\";\n\n if (rule.identifier) {\n finalTranslationString = `${translateString}.${rule.identifier}.${breakingBoundaryProperty}`;\n } else {\n finalTranslationString = `${translateString}.${breakingBoundaryProperty}`;\n }\n } else if (rule.identifier) {\n finalTranslationString = `${translateString}.${rule.identifier}`;\n } else {\n finalTranslationString = translateString;\n }\n\n return shortVersion\n ? `${finalTranslationString}.short`\n : finalTranslationString;\n};\n\n/** @internal */\nexport const generateValidationTranslation = (\n r: Partial<RuleValidationResult>,\n shotVersion = false,\n): [string, Record<string, string | number | boolean> | undefined] => {\n const translationKey = generateTranslationString(r, shotVersion);\n\n if (r.ruleType === RuleType.char && r.chars) {\n return [\n translationKey,\n { ...r, chars: r.chars.map((c) => c.char).join(\"\") },\n ];\n }\n\n return [\n translationKey,\n r as unknown as Record<string, string | number | boolean> | undefined,\n ];\n};\n\nexport default generateValidationTranslation;\n"],"mappings":";;;;AAKA,IAAM,6BACJ,MACA,eAAe,UACJ;CACX,IAAI,KAAK,gBACP,OAAO,cAAc,KAAK;CAE5B,MAAM,kBAAkB,cAAc,KAAK,YAAY;CACvD,IAAI;CAEJ,IACG,SAAS,QAAQ,KAAK,QAAQ,KAAA,KAC9B,SAAS,QAAQ,KAAK,QAAQ,KAAA,GAC/B;EACA,MAAM,2BAA2B,KAAK,kBAClC,KAAK,kBACL,KAAK,MACH,QACA;EAEN,IAAI,KAAK,YACP,yBAAyB,GAAG,gBAAgB,GAAG,KAAK,WAAW,GAAG;OAElE,yBAAyB,GAAG,gBAAgB,GAAG;CAEnD,OAAO,IAAI,KAAK,YACd,yBAAyB,GAAG,gBAAgB,GAAG,KAAK;MAEpD,yBAAyB;CAG3B,OAAO,eACH,GAAG,uBAAuB,UAC1B;AACN;;AAGA,IAAa,iCACX,GACA,cAAc,UACsD;CACpE,MAAM,iBAAiB,0BAA0B,GAAG,WAAW;CAE/D,IAAI,EAAE,aAAa,SAAS,QAAQ,EAAE,OACpC,OAAO,CACL,gBACA;EAAE,GAAG;EAAG,OAAO,EAAE,MAAM,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE;CAAE,CACrD;CAGF,OAAO,CACL,gBACA,CACF;AACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
/* */
|
|
3
3
|
//#region src/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult.ts
|
|
4
|
+
/** @internal */
|
|
4
5
|
var getStatusFromPolicyValidationResult = (isValid, result) => {
|
|
5
6
|
if (isValid === true) {
|
|
6
7
|
if (result.complexity && result.complexity.actual === result.complexity.min && result.complexity.min !== 4) return "warning";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getStatusFromPolicyValidationResult.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult.ts"],"sourcesContent":["import type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport type { ComplexityStatus } from \"@/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator\";\n\nexport const getStatusFromPolicyValidationResult = (\n isValid: ResolvedPolicyValidationResult[\"isValid\"],\n result: ResolvedPolicyValidationResult,\n): ComplexityStatus => {\n if (isValid === true) {\n if (\n result.complexity &&\n result.complexity.actual === result.complexity.min &&\n result.complexity.min !== 4\n ) {\n return \"warning\";\n }\n\n return \"success\";\n } else if (isValid === \"indeterminate\") {\n return \"indeterminate\";\n }\n\n return \"danger\";\n};\n\nexport default getStatusFromPolicyValidationResult;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"getStatusFromPolicyValidationResult.mjs","names":[],"sources":["../../../../../../../../src/components/PasswordCreationField/lib/getStatusFromPolicyValidationResult.ts"],"sourcesContent":["import type { ResolvedPolicyValidationResult } from \"@/components/PasswordCreationField/PasswordCreationField\";\nimport type { ComplexityStatus } from \"@/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator\";\n\n/** @internal */\nexport const getStatusFromPolicyValidationResult = (\n isValid: ResolvedPolicyValidationResult[\"isValid\"],\n result: ResolvedPolicyValidationResult,\n): ComplexityStatus => {\n if (isValid === true) {\n if (\n result.complexity &&\n result.complexity.actual === result.complexity.min &&\n result.complexity.min !== 4\n ) {\n return \"warning\";\n }\n\n return \"success\";\n } else if (isValid === \"indeterminate\") {\n return \"indeterminate\";\n }\n\n return \"danger\";\n};\n\nexport default getStatusFromPolicyValidationResult;\n"],"mappings":";;;;AAIA,IAAa,uCACX,SACA,WACqB;CACrB,IAAI,YAAY,MAAM;EACpB,IACE,OAAO,cACP,OAAO,WAAW,WAAW,OAAO,WAAW,OAC/C,OAAO,WAAW,QAAQ,GAE1B,OAAO;EAGT,OAAO;CACT,OAAO,IAAI,YAAY,iBACrB,OAAO;CAGT,OAAO;AACT"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { startTransition, useEffect, useRef } from "react";
|
|
4
4
|
import { useDebouncedCallback } from "use-debounce";
|
|
5
5
|
//#region src/components/PasswordCreationField/lib/usePolicyValidationResult.ts
|
|
6
|
+
/** @internal */
|
|
6
7
|
var usePolicyValidationResult = (validationPolicy, password, onValidationStart, onValidationResult) => {
|
|
7
8
|
const cache = useRef(null);
|
|
8
9
|
const validatePassword = (pwd) => {
|
|
@@ -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\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":"
|
|
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;AACjC"}
|
|
@@ -4,9 +4,10 @@ import Popover_module_default from "../../Popover.module.mjs";
|
|
|
4
4
|
import { popoverViewportPadding } from "../../viewportPadding.mjs";
|
|
5
5
|
import { popoverWidthStyle } from "../../widthStyle.mjs";
|
|
6
6
|
import clsx from "clsx";
|
|
7
|
-
import { useEffect, useId, useRef
|
|
7
|
+
import { useEffect, useId, useRef } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import {
|
|
9
|
+
import { useEnterAnimation, useExitAnimation } from "@react-aria/utils";
|
|
10
|
+
import { useObjectRef as useObjectRef$1, useOverlayPosition } from "react-aria";
|
|
10
11
|
//#region src/components/Popover/components/NonModalPopoverContent/NonModalPopoverContent.tsx
|
|
11
12
|
var useRepositionWhenAnchorMoves = (anchorRef, isOpen, updatePosition) => {
|
|
12
13
|
useEffect(() => {
|
|
@@ -22,7 +23,19 @@ var useRepositionWhenAnchorMoves = (anchorRef, isOpen, updatePosition) => {
|
|
|
22
23
|
]);
|
|
23
24
|
};
|
|
24
25
|
var NonModalPopoverContent = (props) => {
|
|
25
|
-
const {
|
|
26
|
+
const { isOpen = false, ref, ...rest } = props;
|
|
27
|
+
const overlayRef = useObjectRef$1(ref);
|
|
28
|
+
const isExiting = useExitAnimation(overlayRef, isOpen);
|
|
29
|
+
if (!isOpen && !isExiting) return null;
|
|
30
|
+
return /* @__PURE__ */ jsx(NonModalPopoverContentInner, {
|
|
31
|
+
...rest,
|
|
32
|
+
overlayRef,
|
|
33
|
+
isOpen,
|
|
34
|
+
isExiting
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
var NonModalPopoverContentInner = (props) => {
|
|
38
|
+
const { children, className, withTip, isOpen = false, isExiting, width, id, onOpenChange, overlayRef, triggerRef, placement: requestedPlacement, offset, crossOffset, maxHeight: ignoredMaxHeight, shouldFlip, shouldUpdatePosition, arrowBoundaryOffset, boundaryElement, ...rest } = props;
|
|
26
39
|
const positionProps = {
|
|
27
40
|
placement: requestedPlacement,
|
|
28
41
|
offset,
|
|
@@ -32,9 +45,7 @@ var NonModalPopoverContent = (props) => {
|
|
|
32
45
|
arrowBoundaryOffset,
|
|
33
46
|
boundaryElement
|
|
34
47
|
};
|
|
35
|
-
const overlayRef = useObjectRef(ref);
|
|
36
48
|
const arrowRef = useRef(null);
|
|
37
|
-
const [isEntering, setIsEntering] = useState(true);
|
|
38
49
|
const detailsId = useId();
|
|
39
50
|
const { overlayProps, arrowProps, placement, updatePosition } = useOverlayPosition({
|
|
40
51
|
...positionProps,
|
|
@@ -46,6 +57,8 @@ var NonModalPopoverContent = (props) => {
|
|
|
46
57
|
containerPadding: popoverViewportPadding
|
|
47
58
|
});
|
|
48
59
|
useRepositionWhenAnchorMoves(triggerRef, isOpen, updatePosition);
|
|
60
|
+
const isPositioned = placement !== null;
|
|
61
|
+
const isEntering = useEnterAnimation(overlayRef, isPositioned);
|
|
49
62
|
useEffect(() => {
|
|
50
63
|
const trigger = triggerRef.current;
|
|
51
64
|
if (!isOpen || !trigger) return;
|
|
@@ -68,11 +81,6 @@ var NonModalPopoverContent = (props) => {
|
|
|
68
81
|
document.addEventListener("keydown", closeOnEscape);
|
|
69
82
|
return () => document.removeEventListener("keydown", closeOnEscape);
|
|
70
83
|
}, [isOpen, onOpenChange]);
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
if (!isOpen) setIsEntering(true);
|
|
73
|
-
}, [isOpen]);
|
|
74
|
-
if (!isOpen) return null;
|
|
75
|
-
const isPositioned = placement !== null;
|
|
76
84
|
return /* @__PURE__ */ jsxs("div", {
|
|
77
85
|
...rest,
|
|
78
86
|
...overlayProps,
|
|
@@ -81,7 +89,7 @@ var NonModalPopoverContent = (props) => {
|
|
|
81
89
|
className: clsx(className, Popover_module_default["non-modal"]),
|
|
82
90
|
"data-placement": placement ?? void 0,
|
|
83
91
|
"data-entering": isEntering || void 0,
|
|
84
|
-
|
|
92
|
+
"data-exiting": isExiting || void 0,
|
|
85
93
|
style: {
|
|
86
94
|
...overlayProps.style,
|
|
87
95
|
zIndex: void 0,
|