@ahrowe/ui 0.52.0 → 0.53.0
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/CHANGELOG.md +11 -0
- package/dist/cjs-types/common/otpInput/otpInput.types.d.ts +1 -1
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cjs-types/services/formValidation/index.d.ts +1 -1
- package/dist/cjs-types/services/formValidation/useFormValidatorGroup.d.ts +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs.map +1 -1
- package/dist/esm/common/iconPicker/iconPicker.mjs +1 -1
- package/dist/esm/common/iconPicker/iconPicker.mjs.map +1 -1
- package/dist/esm/common/input/input.mjs +1 -1
- package/dist/esm/common/input/input.mjs.map +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.mjs +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.mjs.map +1 -1
- package/dist/esm/common/multiSelect/multiSelect.mjs +1 -1
- package/dist/esm/common/multiSelect/multiSelect.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
- package/dist/esm/common/otpInput/otpInput.mjs +1 -1
- package/dist/esm/common/otpInput/otpInput.mjs.map +1 -1
- package/dist/esm/common/otpInput/otpInput.types.mjs.map +1 -1
- package/dist/esm/common/radioGroup/radioGroup.mjs +1 -1
- package/dist/esm/common/radioGroup/radioGroup.mjs.map +1 -1
- package/dist/esm/common/timeInput/timeInput.mjs +1 -1
- package/dist/esm/common/timeInput/timeInput.mjs.map +1 -1
- package/dist/esm/services/formValidation/useFormValidatorGroup.mjs +1 -1
- package/dist/esm/services/formValidation/useFormValidatorGroup.mjs.map +1 -1
- package/dist/esm/services/formValidation/validatableComponent.mjs +1 -1
- package/dist/esm/services/formValidation/validatableComponent.mjs.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/types/common/otpInput/otpInput.types.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/services/formValidation/index.d.ts +1 -1
- package/dist/types/services/formValidation/useFormValidatorGroup.d.ts +1 -1
- package/docs/FormValidator.md +23 -1
- package/docs/FormValidatorGroup.md +5 -2
- package/docs/InputDropdown.md +1 -1
- package/docs/MultiSelect.md +1 -1
- package/docs/OtpInput.md +1 -1
- package/docs/RadioGroup.md +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import e from"../button/button.mjs";import{PopoverAlign as t,PopoverPlacement as n}from"../popover/popover.types.mjs";import r from"../popover/popover.mjs";import i from"../tooltip/tooltip.mjs";import a from"../input/input.mjs";import o from"../modal/modal.mjs";import ee from"../maskedInput/maskedInput.mjs";import{clampHour as te,clampToRange as s,formatTime as c,parseTimeString as l,snapMinute as u}from"./timeFunctions.mjs";import ne from"./components/clockDial/clockDial.mjs";import d from"./timeInput.module.mjs";import{useEffect as re,useRef as ie,useState as f}from"react";import p from"classnames";import{FontAwesomeIcon as ae}from"@fortawesome/react-fontawesome";import{faClock as oe}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";function g({value:g,selected:se,onChange:ce=()=>null,onSelect:_=()=>null,formValidator:v=null,isInline:y=!1,isModal:b=!1,noInput:le=!1,noHeader:ue=!1,showClearButton:x=!1,showNowButton:S=!1,minuteStep:C=1,use24Hour:w=!0,minTime:T=null,maxTime:E=null,label:de=``,isValid:fe=!0,errorMessage:D=``,isRequired:O=!1,disabled:k=!1,className:pe=``,style:A,classNames:j,styles:M,...me}){let N=()=>v?v.value||``:g??se??``,[P,F]=f(N),[I,L]=f(!1),[R,z]=f(`hours`),[he,B]=f(!1),[ge,V]=f(!1),[,_e]=f(0),H=N(),[ve,ye]=f(H),U=ie(v);!v&&ve!==H&&(ye(H),F(H)),re(()=>{if(U.current=v,!v)return;let e=()=>{F(v.value||``),_e(e=>e+1)};return v.registerOnUpdateListener(e),()=>v.removeOnUpdateListener(e)},[v]);let be=()=>v?v.
|
|
1
|
+
"use client";import e from"../button/button.mjs";import{PopoverAlign as t,PopoverPlacement as n}from"../popover/popover.types.mjs";import r from"../popover/popover.mjs";import i from"../tooltip/tooltip.mjs";import a from"../input/input.mjs";import o from"../modal/modal.mjs";import ee from"../maskedInput/maskedInput.mjs";import{clampHour as te,clampToRange as s,formatTime as c,parseTimeString as l,snapMinute as u}from"./timeFunctions.mjs";import ne from"./components/clockDial/clockDial.mjs";import d from"./timeInput.module.mjs";import{useEffect as re,useRef as ie,useState as f}from"react";import p from"classnames";import{FontAwesomeIcon as ae}from"@fortawesome/react-fontawesome";import{faClock as oe}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";function g({value:g,selected:se,onChange:ce=()=>null,onSelect:_=()=>null,formValidator:v=null,isInline:y=!1,isModal:b=!1,noInput:le=!1,noHeader:ue=!1,showClearButton:x=!1,showNowButton:S=!1,minuteStep:C=1,use24Hour:w=!0,minTime:T=null,maxTime:E=null,label:de=``,isValid:fe=!0,errorMessage:D=``,isRequired:O=!1,disabled:k=!1,className:pe=``,style:A,classNames:j,styles:M,...me}){let N=()=>v?v.value||``:g??se??``,[P,F]=f(N),[I,L]=f(!1),[R,z]=f(`hours`),[he,B]=f(!1),[ge,V]=f(!1),[,_e]=f(0),H=N(),[ve,ye]=f(H),U=ie(v);!v&&ve!==H&&(ye(H),F(H)),re(()=>{if(U.current=v,!v)return;let e=()=>{F(v.value||``),_e(e=>e+1)};return v.registerOnUpdateListener(e),()=>v.removeOnUpdateListener(e)},[v]);let be=()=>v?v.shouldShowError:!fe||!!D,xe=()=>!!(O||v?.validators.find(e=>e.validatorId===`required`)),W=e=>{let t=e?c(e):null;v&&v.set(t),ce?.(t)},G=e=>{F(e?c(e):``),W(e)},K=l(P),q=K??{hours:12,minutes:0},J=e=>{let t={hours:e.hours,minutes:u(e.minutes,C)};G(s(t,T,E))},Se=e=>{let t={hours:e.hours,minutes:u(e.minutes,C)},n=s(t,T,E);if(G(n),R===`hours`){z(`minutes`);return}_?.(c(n)),y||L(!1)},Y=()=>{k||(z(`hours`),L(!0))},Ce=({previousState:e,nextState:t})=>{if(t.value===e.value)return t;let n=t.value,r=n.slice(0,2);/^\d\d$/.test(r)&&Number(r)>23&&(n=`23${n.slice(2)}`);let i=n.slice(3,5);return/^\d\d$/.test(i)&&Number(i)>59&&(n=`${n.slice(0,3)}59`),n===t.value?t:{...t,value:n}},we=e=>{F(e);let t=l(e);t&&W(t)},Te=()=>{U.current&&(U.current.touched=!0),B(!1),W(l(P))},X=e=>{e!==q.hours>=12&&G({hours:te(q.hours+(e?12:-12)),minutes:q.minutes})},Z=be(),Ee=K?String(w?K.hours:(K.hours+11)%12+1).padStart(2,`0`):`--`,De=K?String(K.minutes).padStart(2,`0`):`--`,Oe=ue?null:h(`div`,{className:p(d.timeInputClockHeader,j?.clockHeader),style:M?.clockHeader,children:[m(`button`,{type:`button`,className:p(d.timeInputHeaderSegment,R===`hours`&&d.timeInputHeaderSegmentActive,j?.headerSegment),style:M?.headerSegment,onClick:()=>z(`hours`),children:Ee}),m(`span`,{className:d.timeInputHeaderColon,children:`:`}),m(`button`,{type:`button`,className:p(d.timeInputHeaderSegment,R===`minutes`&&d.timeInputHeaderSegmentActive,j?.headerSegment),style:M?.headerSegment,onClick:()=>z(`minutes`),children:De}),!w&&h(`div`,{className:p(d.timeInputMeridiem,j?.meridiem),style:M?.meridiem,children:[m(`button`,{type:`button`,className:p(q.hours<12&&d.timeInputMeridiemActive),onClick:()=>X(!1),children:`AM`}),m(`button`,{type:`button`,className:p(q.hours>=12&&d.timeInputMeridiemActive),onClick:()=>X(!0),children:`PM`})]})]}),ke=x||S?h(`div`,{className:p(d.timeInputFooter,j?.footer),style:M?.footer,children:[S&&m(e,{onClick:()=>{let e=new Date;J({hours:e.getHours(),minutes:e.getMinutes()})},children:`Now`}),x&&m(e,{onClick:()=>{G(null),_?.(null)},children:`Clear`})]}):null,Q=h(`div`,{className:p(d.timeInputClock,j?.clock),style:M?.clock,children:[Oe,m(ne,{time:q,mode:R,use24Hour:w,minuteStep:C,onChange:J,onCommit:Se,classNames:j,styles:M}),ke]}),$=le?null:m(a,{autoComplete:`off`,label:`${de}${xe()?` *`:``}`,value:P,icon:m(ae,{icon:oe}),onIconClick:Y,onClick:Y,readOnly:b,disabled:k,isValid:!Z,customInput:m(ee,{mask:`99:99`,beforeMaskedStateChange:Ce}),onChange:e=>we(e),onBlur:Te,onFocus:()=>B(!0),onMouseEnter:()=>V(!0),onMouseLeave:()=>V(!1)}),Ae=y?Q:b?m(o,{hideHeader:!0,isOpen:I,onClose:()=>L(!1),children:Q}):m(r,{isOpen:I,onOpenChange:L,content:Q,placement:n.Bottom,align:t.Start,closeOnTriggerClick:!1,constrainWidth:!1,children:$});return h(`div`,{className:p(d.timeInput,j?.root,pe),style:{...M?.root,...A},...me,children:[(b||y)&&$,Ae,m(i,{variant:`error`,message:v?v.getCurrentErrorMessage()??``:D||``,isVisible:Z&&(he||ge)})]})}export{g as default};
|
|
2
2
|
//# sourceMappingURL=timeInput.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeInput.mjs","names":[],"sources":["../../../../package/common/timeInput/timeInput.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { type TimeValue, parseTimeString, formatTime, snapMinute, clampToRange, clampHour } from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n if (nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed\n ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0')\n : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'hours' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'minutes' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button\n type='button'\n className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(false)}\n >\n AM\n </button>\n <button\n type='button'\n className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(true)}\n >\n PM\n </button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button\n onClick={() => {\n applyTime(null);\n onSelect?.(null);\n }}\n >\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<MaskedInput mask='99:99' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n className={cx(styles.timeInput, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n {...rest}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"timeInput.mjs","names":[],"sources":["../../../../package/common/timeInput/timeInput.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { type TimeValue, parseTimeString, formatTime, snapMinute, clampToRange, clampHour } from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean => (formValidator ? formValidator.shouldShowError : !isValid || !!errorMessage);\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n if (nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed\n ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0')\n : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'hours' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'minutes' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button\n type='button'\n className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(false)}\n >\n AM\n </button>\n <button\n type='button'\n className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(true)}\n >\n PM\n </button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button\n onClick={() => {\n applyTime(null);\n onSelect?.(null);\n }}\n >\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<MaskedInput mask='99:99' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n className={cx(styles.timeInput, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n {...rest}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import e from"./FormValidatorGroupWithForm.mjs";import{useFormValidatorGroupInstance as t}from"@ahrowe/form-validation";function n(n,{
|
|
1
|
+
"use client";import e from"./FormValidatorGroupWithForm.mjs";import{useFormValidatorGroupInstance as t}from"@ahrowe/form-validation";function n(n,{onSubmit:r,onValidate:i,...a}={}){return t(()=>new e(n,null,a),r,i)}export{n as useFormValidatorGroup};
|
|
2
2
|
//# sourceMappingURL=useFormValidatorGroup.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormValidatorGroup.mjs","names":[],"sources":["../../../../package/services/formValidation/useFormValidatorGroup.ts"],"sourcesContent":["import { useFormValidatorGroupInstance } from '@ahrowe/form-validation';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from '@ahrowe/form-validation';\nimport FormValidatorGroupWithForm from './FormValidatorGroupWithForm';\n\n/**\n * @ahrowe/ui's flavour of useFormValidatorGroup: the group it creates has\n * `.Form` attached and defaults `onSubmitError` to an error toast (see\n * FormValidatorGroupWithForm). Reuses the core package's reactive wiring\n * (useFormValidatorGroupInstance) so this and the pure hook share one\n * implementation of \"subscribe a function component to a group\".\n */\nexport function useFormValidatorGroup<TGroup extends FormGroup = FormGroup, TInitial = InferGroupValues<TGroup>>(\n groupDef: TGroup,\n {
|
|
1
|
+
{"version":3,"file":"useFormValidatorGroup.mjs","names":[],"sources":["../../../../package/services/formValidation/useFormValidatorGroup.ts"],"sourcesContent":["import { useFormValidatorGroupInstance } from '@ahrowe/form-validation';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from '@ahrowe/form-validation';\nimport FormValidatorGroupWithForm from './FormValidatorGroupWithForm';\n\n/**\n * @ahrowe/ui's flavour of useFormValidatorGroup: the group it creates has\n * `.Form` attached and defaults `onSubmitError` to an error toast (see\n * FormValidatorGroupWithForm). Reuses the core package's reactive wiring\n * (useFormValidatorGroupInstance) so this and the pure hook share one\n * implementation of \"subscribe a function component to a group\".\n */\nexport function useFormValidatorGroup<TGroup extends FormGroup = FormGroup, TInitial = InferGroupValues<TGroup>>(\n groupDef: TGroup,\n { onSubmit, onValidate, ...options }: FormValidatorGroupOptions<TGroup, TInitial> = {},\n): FormValidatorGroupWithForm<TGroup, TInitial> {\n return useFormValidatorGroupInstance(\n () => new FormValidatorGroupWithForm(groupDef, null, options),\n onSubmit,\n onValidate,\n );\n}\n"],"mappings":"qIAWA,SAAgB,EACd,EACA,CAAE,WAAU,aAAY,GAAG,GAAyD,CAAC,EACvC,CAC9C,OAAO,MACC,IAAI,EAA2B,EAAU,KAAM,CAAO,EAC5D,EACA,CACF,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import e from"../../common/tooltip/tooltip.mjs";import{PureComponent as t}from"react";import{jsx as n}from"react/jsx-runtime";var r=class extends t{static{this.defaultProps={formValidator:null,onMouseEnter:null,onMouseLeave:null,onFocus:null,onBlur:null,onChange:null,errorMessage:``,isValid:!1,isRequired:!1,label:``}}constructor(e){super(e);let{formValidator:t}=e;t&&(t.label=e.label??``,t.validate(),t.registerOnUpdateListener(()=>{this.forceUpdate()})),this.state={isFocused:!1,isHovered:!1},this.onMouseEnter=this.onMouseEnter.bind(this),this.onMouseLeave=this.onMouseLeave.bind(this),this.onFocus=this.onFocus.bind(this),this.onBlur=this.onBlur.bind(this),this.hasError=this.hasError.bind(this),this.renderTooltip=this.renderTooltip.bind(this),this.onChange=this.onChange.bind(this)}componentDidMount(){setTimeout(()=>this.setState({isFocused:!1,isHovered:!1}),1)}componentDidUpdate(e){let{formValidator:t}=this.props;e.formValidator&&t&&e.formValidator!==t&&t.registerOnUpdateListener(()=>{this.forceUpdate()})}onMouseEnter(e){let{onMouseEnter:t}=this.props;this.setState({isHovered:!0}),t&&t(e)}onMouseLeave(e){let{onMouseLeave:t}=this.props;this.setState({isHovered:!1}),t&&t(e)}onFocus(e){let{onFocus:t}=this.props;this.setState({isFocused:!0}),t&&t(e)}onBlur(e){let{formValidator:t,onBlur:n}=this.props;t&&(t.touched=!0),this.setState({isFocused:!1}),n&&n(e)}hasError(){let{errorMessage:e,isValid:t,formValidator:n}=this.props;return n?n.
|
|
1
|
+
"use client";import e from"../../common/tooltip/tooltip.mjs";import{PureComponent as t}from"react";import{jsx as n}from"react/jsx-runtime";var r=class extends t{static{this.defaultProps={formValidator:null,onMouseEnter:null,onMouseLeave:null,onFocus:null,onBlur:null,onChange:null,errorMessage:``,isValid:!1,isRequired:!1,label:``}}constructor(e){super(e);let{formValidator:t}=e;t&&(t.label=e.label??``,t.validate(),t.registerOnUpdateListener(()=>{this.forceUpdate()})),this.state={isFocused:!1,isHovered:!1},this.onMouseEnter=this.onMouseEnter.bind(this),this.onMouseLeave=this.onMouseLeave.bind(this),this.onFocus=this.onFocus.bind(this),this.onBlur=this.onBlur.bind(this),this.hasError=this.hasError.bind(this),this.renderTooltip=this.renderTooltip.bind(this),this.onChange=this.onChange.bind(this)}componentDidMount(){setTimeout(()=>this.setState({isFocused:!1,isHovered:!1}),1)}componentDidUpdate(e){let{formValidator:t}=this.props;e.formValidator&&t&&e.formValidator!==t&&t.registerOnUpdateListener(()=>{this.forceUpdate()})}onMouseEnter(e){let{onMouseEnter:t}=this.props;this.setState({isHovered:!0}),t&&t(e)}onMouseLeave(e){let{onMouseLeave:t}=this.props;this.setState({isHovered:!1}),t&&t(e)}onFocus(e){let{onFocus:t}=this.props;this.setState({isFocused:!0}),t&&t(e)}onBlur(e){let{formValidator:t,onBlur:n}=this.props;t&&(t.touched=!0),this.setState({isFocused:!1}),n&&n(e)}hasError(){let{errorMessage:e,isValid:t,formValidator:n}=this.props;return n?n.shouldShowError:!t||!!e}isRequired(){let{isRequired:e,formValidator:t}=this.props;return!!(e||t&&t.validators.find(e=>e.validatorId===`required`))}renderTooltip(){let{errorMessage:t,formValidator:r}=this.props,{isHovered:i,isFocused:a}=this.state;return n(e,{variant:`error`,message:r?r.getCurrentErrorMessage():t||``,isVisible:this.hasError()&&(a||i)})}onChange(e){let{onChange:t,formValidator:n}=this.props;if(n){let t=e;e&&e.target&&(t=e.target.value),n.set(t)}t&&t(e)}};export{r as default};
|
|
2
2
|
//# sourceMappingURL=validatableComponent.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validatableComponent.mjs","names":[],"sources":["../../../../package/services/formValidation/validatableComponent.tsx"],"sourcesContent":["import React, { PureComponent } from 'react';\nimport { FormValidator } from '@ahrowe/form-validation';\nimport Tooltip from 'components/common/tooltip';\n\nexport interface ValidatableComponentProps {\n formValidator?: FormValidator | null;\n onMouseEnter?: ((event: React.MouseEvent) => void) | null;\n onMouseLeave?: ((event: React.MouseEvent) => void) | null;\n onFocus?: ((event: React.FocusEvent) => void) | null;\n onBlur?: ((event: React.FocusEvent) => void) | null;\n onChange?: ((value: unknown) => void) | null;\n errorMessage?: string;\n isValid?: boolean;\n isRequired?: boolean;\n label?: string;\n}\n\nexport interface ValidatableComponentState {\n isFocused: boolean;\n isHovered: boolean;\n}\n\n/**\n * Base class that extends PureComponent with FormValidator integration.\n * Manages hover/focus state and renders error tooltips.\n */\nexport default class ValidatableComponent<\n P extends ValidatableComponentProps = ValidatableComponentProps,\n S extends ValidatableComponentState = ValidatableComponentState,\n> extends PureComponent<P, S> {\n static defaultProps: Partial<ValidatableComponentProps> = {\n formValidator: null,\n onMouseEnter: null,\n onMouseLeave: null,\n onFocus: null,\n onBlur: null,\n onChange: null,\n errorMessage: '',\n isValid: false,\n isRequired: false,\n label: '',\n };\n\n constructor(props: P) {\n super(props);\n const { formValidator } = props;\n\n if (formValidator) {\n formValidator.label = props.label ?? '';\n formValidator.validate();\n formValidator.registerOnUpdateListener(() => {\n this.forceUpdate();\n });\n }\n\n this.state = { isFocused: false, isHovered: false } as S;\n\n this.onMouseEnter = this.onMouseEnter.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onFocus = this.onFocus.bind(this);\n this.onBlur = this.onBlur.bind(this);\n this.hasError = this.hasError.bind(this);\n this.renderTooltip = this.renderTooltip.bind(this);\n this.onChange = this.onChange.bind(this);\n }\n\n componentDidMount(): void {\n setTimeout(() => this.setState({ isFocused: false, isHovered: false } as S), 1);\n }\n\n componentDidUpdate(prevProps: P): void {\n const { formValidator } = this.props;\n if (prevProps.formValidator && formValidator && prevProps.formValidator !== formValidator) {\n formValidator.registerOnUpdateListener(() => {\n this.forceUpdate();\n });\n }\n }\n\n onMouseEnter(event: React.MouseEvent): void {\n const { onMouseEnter } = this.props;\n this.setState({ isHovered: true } as unknown as S);\n if (onMouseEnter) onMouseEnter(event);\n }\n\n onMouseLeave(event: React.MouseEvent): void {\n const { onMouseLeave } = this.props;\n this.setState({ isHovered: false } as unknown as S);\n if (onMouseLeave) onMouseLeave(event);\n }\n\n onFocus(event: React.FocusEvent): void {\n const { onFocus } = this.props;\n this.setState({ isFocused: true } as unknown as S);\n if (onFocus) onFocus(event);\n }\n\n onBlur(event: React.FocusEvent): void {\n const { formValidator, onBlur } = this.props;\n if (formValidator) formValidator.touched = true;\n this.setState({ isFocused: false } as unknown as S);\n if (onBlur) onBlur(event);\n }\n\n hasError(): boolean {\n const { errorMessage, isValid, formValidator } = this.props;\n return formValidator ? formValidator.
|
|
1
|
+
{"version":3,"file":"validatableComponent.mjs","names":[],"sources":["../../../../package/services/formValidation/validatableComponent.tsx"],"sourcesContent":["import React, { PureComponent } from 'react';\nimport { FormValidator } from '@ahrowe/form-validation';\nimport Tooltip from 'components/common/tooltip';\n\nexport interface ValidatableComponentProps {\n formValidator?: FormValidator | null;\n onMouseEnter?: ((event: React.MouseEvent) => void) | null;\n onMouseLeave?: ((event: React.MouseEvent) => void) | null;\n onFocus?: ((event: React.FocusEvent) => void) | null;\n onBlur?: ((event: React.FocusEvent) => void) | null;\n onChange?: ((value: unknown) => void) | null;\n errorMessage?: string;\n isValid?: boolean;\n isRequired?: boolean;\n label?: string;\n}\n\nexport interface ValidatableComponentState {\n isFocused: boolean;\n isHovered: boolean;\n}\n\n/**\n * Base class that extends PureComponent with FormValidator integration.\n * Manages hover/focus state and renders error tooltips.\n */\nexport default class ValidatableComponent<\n P extends ValidatableComponentProps = ValidatableComponentProps,\n S extends ValidatableComponentState = ValidatableComponentState,\n> extends PureComponent<P, S> {\n static defaultProps: Partial<ValidatableComponentProps> = {\n formValidator: null,\n onMouseEnter: null,\n onMouseLeave: null,\n onFocus: null,\n onBlur: null,\n onChange: null,\n errorMessage: '',\n isValid: false,\n isRequired: false,\n label: '',\n };\n\n constructor(props: P) {\n super(props);\n const { formValidator } = props;\n\n if (formValidator) {\n formValidator.label = props.label ?? '';\n formValidator.validate();\n formValidator.registerOnUpdateListener(() => {\n this.forceUpdate();\n });\n }\n\n this.state = { isFocused: false, isHovered: false } as S;\n\n this.onMouseEnter = this.onMouseEnter.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onFocus = this.onFocus.bind(this);\n this.onBlur = this.onBlur.bind(this);\n this.hasError = this.hasError.bind(this);\n this.renderTooltip = this.renderTooltip.bind(this);\n this.onChange = this.onChange.bind(this);\n }\n\n componentDidMount(): void {\n setTimeout(() => this.setState({ isFocused: false, isHovered: false } as S), 1);\n }\n\n componentDidUpdate(prevProps: P): void {\n const { formValidator } = this.props;\n if (prevProps.formValidator && formValidator && prevProps.formValidator !== formValidator) {\n formValidator.registerOnUpdateListener(() => {\n this.forceUpdate();\n });\n }\n }\n\n onMouseEnter(event: React.MouseEvent): void {\n const { onMouseEnter } = this.props;\n this.setState({ isHovered: true } as unknown as S);\n if (onMouseEnter) onMouseEnter(event);\n }\n\n onMouseLeave(event: React.MouseEvent): void {\n const { onMouseLeave } = this.props;\n this.setState({ isHovered: false } as unknown as S);\n if (onMouseLeave) onMouseLeave(event);\n }\n\n onFocus(event: React.FocusEvent): void {\n const { onFocus } = this.props;\n this.setState({ isFocused: true } as unknown as S);\n if (onFocus) onFocus(event);\n }\n\n onBlur(event: React.FocusEvent): void {\n const { formValidator, onBlur } = this.props;\n if (formValidator) formValidator.touched = true;\n this.setState({ isFocused: false } as unknown as S);\n if (onBlur) onBlur(event);\n }\n\n hasError(): boolean {\n const { errorMessage, isValid, formValidator } = this.props;\n return formValidator ? formValidator.shouldShowError : !isValid || !!errorMessage;\n }\n\n isRequired(): boolean {\n const { isRequired, formValidator } = this.props;\n return !!(\n isRequired ||\n (formValidator &&\n formValidator.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'))\n );\n }\n\n renderTooltip(): React.ReactNode {\n const { errorMessage, formValidator } = this.props;\n const { isHovered, isFocused } = this.state;\n return (\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={this.hasError() && (isFocused || isHovered)}\n />\n );\n }\n\n onChange(newVal: unknown): void {\n const { onChange, formValidator } = this.props;\n if (formValidator) {\n let extractedVal = newVal;\n if (newVal && (newVal as React.ChangeEvent<HTMLInputElement>).target) {\n extractedVal = (newVal as React.ChangeEvent<HTMLInputElement>).target.value;\n }\n formValidator.set(extractedVal);\n }\n if (onChange) onChange(newVal);\n }\n}\n"],"mappings":"2IA0BA,IAAqB,EAArB,cAGU,CAAoB,QAC8B,KAAA,aAAA,CACxD,cAAe,KACf,aAAc,KACd,aAAc,KACd,QAAS,KACT,OAAQ,KACR,SAAU,KACV,aAAc,GACd,QAAS,GACT,WAAY,GACZ,MAAO,EACT,EAEA,YAAY,EAAU,CACpB,MAAM,CAAK,EACX,GAAM,CAAE,iBAAkB,EAEtB,IACF,EAAc,MAAQ,EAAM,OAAS,GACrC,EAAc,SAAS,EACvB,EAAc,6BAA+B,CAC3C,KAAK,YAAY,CACnB,CAAC,GAGH,KAAK,MAAQ,CAAE,UAAW,GAAO,UAAW,EAAM,EAElD,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,OAAS,KAAK,OAAO,KAAK,IAAI,EACnC,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,EACvC,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,CACzC,CAEA,mBAA0B,CACxB,eAAiB,KAAK,SAAS,CAAE,UAAW,GAAO,UAAW,EAAM,CAAM,EAAG,CAAC,CAChF,CAEA,mBAAmB,EAAoB,CACrC,GAAM,CAAE,iBAAkB,KAAK,MAC3B,EAAU,eAAiB,GAAiB,EAAU,gBAAkB,GAC1E,EAAc,6BAA+B,CAC3C,KAAK,YAAY,CACnB,CAAC,CAEL,CAEA,aAAa,EAA+B,CAC1C,GAAM,CAAE,gBAAiB,KAAK,MAC9B,KAAK,SAAS,CAAE,UAAW,EAAK,CAAiB,EAC7C,GAAc,EAAa,CAAK,CACtC,CAEA,aAAa,EAA+B,CAC1C,GAAM,CAAE,gBAAiB,KAAK,MAC9B,KAAK,SAAS,CAAE,UAAW,EAAM,CAAiB,EAC9C,GAAc,EAAa,CAAK,CACtC,CAEA,QAAQ,EAA+B,CACrC,GAAM,CAAE,WAAY,KAAK,MACzB,KAAK,SAAS,CAAE,UAAW,EAAK,CAAiB,EAC7C,GAAS,EAAQ,CAAK,CAC5B,CAEA,OAAO,EAA+B,CACpC,GAAM,CAAE,gBAAe,UAAW,KAAK,MACnC,IAAe,EAAc,QAAU,IAC3C,KAAK,SAAS,CAAE,UAAW,EAAM,CAAiB,EAC9C,GAAQ,EAAO,CAAK,CAC1B,CAEA,UAAoB,CAClB,GAAM,CAAE,eAAc,UAAS,iBAAkB,KAAK,MACtD,OAAO,EAAgB,EAAc,gBAAkB,CAAC,GAAW,CAAC,CAAC,CACvE,CAEA,YAAsB,CACpB,GAAM,CAAE,aAAY,iBAAkB,KAAK,MAC3C,MAAO,CAAC,EACN,GACC,GACC,EAAc,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,EAErG,CAEA,eAAiC,CAC/B,GAAM,CAAE,eAAc,iBAAkB,KAAK,MACvC,CAAE,YAAW,aAAc,KAAK,MACtC,OACE,EAAC,EAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,EAAI,GAAgB,GAClF,UAAW,KAAK,SAAS,IAAM,GAAa,EAC7C,CAAA,CAEL,CAEA,SAAS,EAAuB,CAC9B,GAAM,CAAE,WAAU,iBAAkB,KAAK,MACzC,GAAI,EAAe,CACjB,IAAI,EAAe,EACf,GAAW,EAA+C,SAC5D,EAAgB,EAA+C,OAAO,OAExE,EAAc,IAAI,CAAY,CAChC,CACI,GAAU,EAAS,CAAM,CAC/B,CACF"}
|