@ahrowe/ui 0.27.0 → 0.28.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/dist/esm/common/accordion/accordion.mjs +1 -1
- package/dist/esm/common/accordion/accordion.mjs.map +1 -1
- package/dist/esm/common/colorPicker/colorPicker.mjs +1 -1
- package/dist/esm/common/colorPicker/colorPicker.mjs.map +1 -1
- package/dist/esm/common/confirmModal/confirmModal.mjs +1 -1
- package/dist/esm/common/confirmModal/confirmModal.mjs.map +1 -1
- package/dist/esm/common/dropZone/dropZone.mjs +1 -1
- package/dist/esm/common/dropZone/dropZone.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs.map +1 -1
- package/dist/esm/common/hooks/useAnchorTracking.mjs +2 -0
- package/dist/esm/common/hooks/useAnchorTracking.mjs.map +1 -0
- package/dist/esm/common/idleManager/idleManager.mjs +1 -1
- package/dist/esm/common/idleManager/idleManager.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/klipyPicker/components/gifView/gifView.mjs +1 -1
- package/dist/esm/common/klipyPicker/components/gifView/gifView.mjs.map +1 -1
- package/dist/esm/common/multiSelect/multiSelect.mjs +2 -0
- package/dist/esm/common/multiSelect/multiSelect.mjs.map +1 -0
- package/dist/esm/common/multiSelect/multiSelect.module.mjs +2 -0
- package/dist/esm/common/multiSelect/multiSelect.module.mjs.map +1 -0
- package/dist/esm/common/overscroll/overscroll.mjs +1 -1
- package/dist/esm/common/overscroll/overscroll.mjs.map +1 -1
- package/dist/esm/common/pagination/pagination.mjs +2 -0
- package/dist/esm/common/pagination/pagination.mjs.map +1 -0
- package/dist/esm/common/pagination/pagination.module.mjs +2 -0
- package/dist/esm/common/pagination/pagination.module.mjs.map +1 -0
- package/dist/esm/common/popover/usePopoverPosition.mjs +1 -1
- package/dist/esm/common/popover/usePopoverPosition.mjs.map +1 -1
- package/dist/esm/common/timer/timer.mjs.map +1 -1
- package/dist/esm/common/tree/flattenTree.mjs +2 -0
- package/dist/esm/common/tree/flattenTree.mjs.map +1 -0
- package/dist/esm/common/tree/tree.mjs +2 -0
- package/dist/esm/common/tree/tree.mjs.map +1 -0
- package/dist/esm/common/tree/tree.module.mjs +2 -0
- package/dist/esm/common/tree/tree.module.mjs.map +1 -0
- package/dist/esm/common/virtualList/virtualList.mjs +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
- package/dist/esm/common/virtualList/virtualRow.mjs.map +1 -1
- package/dist/esm/index.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/style.css +1 -1
- package/dist/types/package/common/configProvider/configProvider.types.d.ts +6 -0
- package/dist/types/package/common/floatingMenu/useFloatingPosition.d.ts +4 -6
- package/dist/types/package/common/hooks/useAnchorTracking.d.ts +40 -0
- package/dist/types/package/common/inputDropdown/inputDropdown.types.d.ts +6 -0
- package/dist/types/package/common/multiSelect/index.d.ts +2 -0
- package/dist/types/package/common/multiSelect/multiSelect.d.ts +4 -0
- package/dist/types/package/common/multiSelect/multiSelect.types.d.ts +62 -0
- package/dist/types/package/common/pagination/index.d.ts +2 -0
- package/dist/types/package/common/pagination/pagination.d.ts +4 -0
- package/dist/types/package/common/pagination/pagination.types.d.ts +30 -0
- package/dist/types/package/common/popover/usePopoverPosition.d.ts +4 -2
- package/dist/types/package/common/tree/flattenTree.d.ts +3 -0
- package/dist/types/package/common/tree/index.d.ts +3 -0
- package/dist/types/package/common/tree/tree.d.ts +4 -0
- package/dist/types/package/common/tree/tree.types.d.ts +62 -0
- package/dist/types/package/common/virtualList/virtualList.types.d.ts +8 -0
- package/dist/types/package/common/virtualList/virtualRow.d.ts +1 -1
- package/dist/types/package/index.d.ts +6 -0
- package/docs/CLAUDE.md +3 -0
- package/docs/InputDropdown.md +3 -0
- package/docs/MultiSelect.md +100 -0
- package/docs/Pagination.md +72 -0
- package/docs/Tree.md +95 -0
- package/docs/VirtualList.md +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timer.mjs","names":[],"sources":["../../../../package/common/timer/timer.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ReactElement,\n} from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faPlus, faMinus, faPause, faPlay, faXmark } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport Button from '../button';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults } from '../configProvider';\nimport { DEFAULT_CHIME_DATA_URI } from './timer.chime';\nimport type { TimerHandle, TimerProps, TimerStatus } from './timer.types';\nimport styles from './timer.module.pcss';\n\nconst TICK_MS = 200;\nconst RIPPLE_SPAWN_INTERVAL_MS = 1000;\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\nfunction formatTimeDefault(remainingMs: number) {\n const totalSeconds = Math.ceil(remainingMs / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, '0');\n const ss = String(seconds).padStart(2, '0');\n return hours > 0 ? `${hours}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nconst Timer = forwardRef<TimerHandle, TimerProps>(function Timer(props, ref) {\n const {\n durationSeconds,\n autoStart = true,\n resetOnDurationChange = true,\n\n onTick,\n onComplete,\n onStart,\n onPause,\n onResume,\n onCancel,\n onAddTime,\n onRemoveTime,\n\n showControls = true,\n hideAddButton = false,\n hideRemoveButton = false,\n hidePauseButton = false,\n hideCancelButton = false,\n adjustSeconds = 30,\n maxSeconds,\n\n label,\n formatTime = formatTimeDefault,\n size = '160px',\n strokeWidth = 10,\n counterClockwise = false,\n\n urgentThreshold = 0.1,\n urgentMinSeconds = 3,\n pulseOnUrgent = true,\n showRunningRipples = false,\n\n playSoundOnComplete = false,\n soundUrl,\n soundVolume = 0.5,\n notifyOnComplete = false,\n notificationTitle,\n notificationBody,\n\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Timer', props);\n\n const initialMs = durationSeconds * 1000;\n const [status, setStatusState] = useState<TimerStatus>(autoStart ? 'running' : 'idle');\n const [remainingMs, setRemainingMsState] = useState(initialMs);\n const [epoch, setEpoch] = useState(0);\n const [ripples, setRipples] = useState<number[]>([]);\n\n const remainingRef = useRef(remainingMs);\n const statusRef = useRef(status);\n const totalMsRef = useRef(initialMs);\n const completedFiredRef = useRef(false);\n const notifyPermissionRequestedRef = useRef(false);\n const mountedRef = useRef(false);\n const rippleIdRef = useRef(0);\n\n function setRemaining(next: number) {\n remainingRef.current = next;\n setRemainingMsState(next);\n }\n\n function setStatus(next: TimerStatus) {\n statusRef.current = next;\n setStatusState(next);\n }\n\n function bumpEpoch() {\n setEpoch((e) => e + 1);\n }\n\n // Ticking effect. Re-derives the remaining time from Date.now() every tick (rather than\n // accumulating setInterval's own drift), so it stays accurate over long countdowns. Any\n // external mutation of remainingRef (addTime/removeTime while already running, or a resume)\n // must bump `epoch` so this effect re-arms and re-captures a fresh start/startRemaining —\n // without that, a stale `startRemaining` captured before the mutation would silently\n // overwrite it on the next tick.\n useEffect(() => {\n if (status !== 'running') return undefined;\n const start = Date.now();\n const startRemaining = remainingRef.current;\n const id = setInterval(() => {\n const next = Math.max(0, startRemaining - (Date.now() - start));\n setRemaining(next);\n onTick?.(next);\n if (next <= 0) setStatus('completed');\n }, TICK_MS);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status, epoch]);\n\n // Fires onComplete exactly once per completion, plus the opt-in sound/notification.\n useEffect(() => {\n if (status === 'completed' && !completedFiredRef.current) {\n completedFiredRef.current = true;\n onComplete?.();\n if (playSoundOnComplete) {\n try {\n const audio = new Audio(soundUrl || DEFAULT_CHIME_DATA_URI);\n audio.volume = soundVolume;\n // play() can reject (autoplay policy) or, in some environments, return undefined\n // instead of a Promise — never let a blocked/unsupported playback surface as an error.\n audio.play()?.catch(() => {});\n } catch {\n // Audio unavailable/unsupported — fail silently.\n }\n }\n if (notifyOnComplete && typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n try {\n new Notification(notificationTitle ?? 'Timer done', {\n body: notificationBody ?? (typeof label === 'string' ? label : undefined),\n });\n } catch {\n // Some browsers (e.g. certain mobile Safari versions) throw constructing\n // Notification outside specific contexts — fail silently, as documented.\n }\n }\n }\n if (status !== 'completed') completedFiredRef.current = false;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status]);\n\n // durationSeconds prop change: reset (and optionally restart) at the new duration. Skips\n // the initial mount, since autoStart/initial state already cover that.\n useEffect(() => {\n if (!mountedRef.current) {\n mountedRef.current = true;\n return;\n }\n const nextMs = durationSeconds * 1000;\n totalMsRef.current = nextMs;\n setRemaining(nextMs);\n completedFiredRef.current = false;\n bumpEpoch();\n if (resetOnDurationChange) {\n setStatus(autoStart ? 'running' : 'idle');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [durationSeconds]);\n\n // Running-ripple spawner: spawns a new ripple roughly every RIPPLE_SPAWN_INTERVAL_MS while\n // running, each animating once (via CSS, `forwards`) and removing itself on `onAnimationEnd`.\n // Pausing (or otherwise leaving `running`) only stops new spawns here — it doesn't touch\n // `ripples` — so whichever ripples are already mid-flight keep animating to completion\n // instead of vanishing mid-cycle.\n useEffect(() => {\n if (!showRunningRipples || status !== 'running' || prefersReducedMotion()) return undefined;\n function spawnRipple() {\n rippleIdRef.current += 1;\n setRipples((prev) => [...prev, rippleIdRef.current]);\n }\n spawnRipple();\n const id = setInterval(spawnRipple, RIPPLE_SPAWN_INTERVAL_MS);\n return () => clearInterval(id);\n }, [showRunningRipples, status]);\n\n function handleRippleAnimationEnd(id: number) {\n setRipples((prev) => prev.filter((existingId) => existingId !== id));\n }\n\n function requestNotificationPermissionIfNeeded() {\n if (!notifyOnComplete || notifyPermissionRequestedRef.current) return;\n if (typeof Notification === 'undefined' || Notification.permission !== 'default') return;\n notifyPermissionRequestedRef.current = true;\n Notification.requestPermission().catch(() => {});\n }\n\n function start() {\n requestNotificationPermissionIfNeeded();\n if (statusRef.current === 'completed' || statusRef.current === 'cancelled') {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n }\n bumpEpoch();\n setStatus('running');\n onStart?.();\n }\n\n function pause() {\n if (statusRef.current !== 'running') return;\n setStatus('paused');\n onPause?.();\n }\n\n function resume() {\n if (statusRef.current !== 'paused') return;\n bumpEpoch();\n setStatus('running');\n onResume?.();\n }\n\n function addTime(seconds: number) {\n const capped = maxSeconds != null ? maxSeconds * 1000 : Infinity;\n const next = Math.min(remainingRef.current + seconds * 1000, capped);\n setRemaining(next);\n bumpEpoch();\n onAddTime?.(seconds, Math.round(next / 1000));\n if (statusRef.current === 'completed' && next > 0) {\n completedFiredRef.current = false;\n setStatus('running');\n }\n }\n\n function removeTime(seconds: number) {\n const next = Math.max(0, remainingRef.current - seconds * 1000);\n setRemaining(next);\n bumpEpoch();\n onRemoveTime?.(seconds, Math.round(next / 1000));\n if (next <= 0 && statusRef.current === 'running') setStatus('completed');\n }\n\n function cancel() {\n setRemaining(totalMsRef.current);\n setStatus('cancelled');\n onCancel?.();\n }\n\n function reset() {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n setStatus('idle');\n }\n\n useImperativeHandle(ref, () => ({\n start,\n pause,\n resume,\n addTime,\n removeTime,\n cancel,\n reset,\n getStatus: () => statusRef.current,\n getRemainingMs: () => remainingRef.current,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }));\n\n const radius = 50 - strokeWidth / 2;\n const circumference = useMemo(() => 2 * Math.PI * radius, [radius]);\n const clampedFraction = totalMsRef.current > 0 ? Math.min(1, remainingMs / totalMsRef.current) : 0;\n const dashOffset = circumference * (1 - clampedFraction);\n const urgentMs = Math.max(totalMsRef.current * urgentThreshold, urgentMinSeconds * 1000);\n const isUrgent = status === 'running' && remainingMs <= urgentMs;\n const isCritical = isUrgent && remainingMs <= Math.min(5000, urgentMs);\n const isPaused = status === 'paused';\n\n // The pause button doubles as a play/restart button whenever there's nothing to pause —\n // idle (autoStart={false}), completed, or cancelled — rather than hiding itself, so there's\n // always a way to (re)start the countdown from the built-in controls alone.\n const showAddButton = showControls && !hideAddButton;\n const showRemoveButton = showControls && !hideRemoveButton;\n const showPauseButton = showControls && !hidePauseButton;\n const pauseButtonIcon = status === 'running' ? faPause : faPlay;\n const pauseButtonTitle = status === 'running' ? 'Pause' : isPaused ? 'Resume' : status === 'idle' ? 'Start' : 'Restart';\n const handlePauseButtonClick = status === 'running' ? pause : isPaused ? resume : start;\n const showCancelButton = showControls && !hideCancelButton;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timer,\n pulseOnUrgent && isUrgent && styles.timerPulsing,\n isCritical && styles.timerCritical,\n className,\n classNames?.root,\n )}\n style={{\n '--timer-size': size,\n '--timer-stroke-width': `${strokeWidth}px`,\n ...style,\n ...slotStyles?.root,\n } as React.CSSProperties}\n >\n <div className={cx(styles.timerRingWrapper, classNames?.ringWrapper)} style={slotStyles?.ringWrapper}>\n {ripples.length > 0 && (\n <div className={cx(styles.timerRipples, classNames?.ripples)} style={slotStyles?.ripples}>\n {ripples.map((id) => (\n <span\n key={id}\n className={cx(styles.timerRipple, classNames?.ripple)}\n style={slotStyles?.ripple}\n onAnimationEnd={() => handleRippleAnimationEnd(id)}\n />\n ))}\n </div>\n )}\n <svg\n className={cx(styles.timerRingSvg, classNames?.ringSvg)}\n viewBox=\"0 0 100 100\"\n style={slotStyles?.ringSvg}\n >\n <circle\n className={cx(styles.timerRingTrack, classNames?.ringTrack)}\n cx=\"50\"\n cy=\"50\"\n r={radius}\n style={slotStyles?.ringTrack}\n />\n <circle\n className={cx(styles.timerRingProgress, isUrgent && styles.timerRingProgressUrgent, classNames?.ringProgress)}\n cx=\"50\"\n cy=\"50\"\n r={radius}\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n style={{\n transition: isPaused ? 'none' : undefined,\n transform: counterClockwise ? 'rotate(-90deg)' : undefined,\n ...slotStyles?.ringProgress,\n }}\n />\n </svg>\n <div className={cx(styles.timerDisplay, classNames?.display)} style={slotStyles?.display}>\n <span className={cx(styles.timerTime, classNames?.time)} style={slotStyles?.time}>\n {formatTime(remainingMs)}\n </span>\n {label && (\n <span className={cx(styles.timerLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n </span>\n )}\n </div>\n </div>\n\n {showControls && (\n <div className={cx(styles.timerControls, classNames?.controls)} style={slotStyles?.controls}>\n <div className={styles.timerControlsRow}>\n {showRemoveButton && (\n <ActionIcon\n icon={faMinus}\n title={`Remove ${adjustSeconds}s`}\n onClick={() => removeTime(adjustSeconds)}\n className={cx(styles.timerAdjustButton, classNames?.removeButton)}\n style={slotStyles?.removeButton}\n />\n )}\n {showPauseButton && (\n <Button\n size={ButtonSize.Small}\n icon={pauseButtonIcon}\n title={pauseButtonTitle}\n onClick={handlePauseButtonClick}\n className={classNames?.pauseButton}\n style={slotStyles?.pauseButton}\n />\n )}\n {showAddButton && (\n <ActionIcon\n icon={faPlus}\n title={`Add ${adjustSeconds}s`}\n onClick={() => addTime(adjustSeconds)}\n className={cx(styles.timerAdjustButton, classNames?.addButton)}\n style={slotStyles?.addButton}\n />\n )}\n </div>\n {showCancelButton && (\n <ActionIcon\n icon={faXmark}\n title=\"Cancel timer\"\n onClick={cancel}\n className={cx(styles.timerCancelButton, classNames?.cancelButton)}\n style={slotStyles?.cancelButton}\n />\n )}\n </div>\n )}\n </div>\n );\n});\n\nTimer.displayName = 'Timer';\n\nexport default Timer;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"timer.mjs","names":[],"sources":["../../../../package/common/timer/timer.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport cx from 'classnames';\nimport { faPlus, faMinus, faPause, faPlay, faXmark } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport Button from '../button';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults } from '../configProvider';\nimport { DEFAULT_CHIME_DATA_URI } from './timer.chime';\nimport type { TimerHandle, TimerProps, TimerStatus } from './timer.types';\nimport styles from './timer.module.pcss';\n\nconst TICK_MS = 200;\nconst RIPPLE_SPAWN_INTERVAL_MS = 1000;\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\nfunction formatTimeDefault(remainingMs: number) {\n const totalSeconds = Math.ceil(remainingMs / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, '0');\n const ss = String(seconds).padStart(2, '0');\n return hours > 0 ? `${hours}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nconst Timer = forwardRef<TimerHandle, TimerProps>(function Timer(props, ref) {\n const {\n durationSeconds,\n autoStart = true,\n resetOnDurationChange = true,\n\n onTick,\n onComplete,\n onStart,\n onPause,\n onResume,\n onCancel,\n onAddTime,\n onRemoveTime,\n\n showControls = true,\n hideAddButton = false,\n hideRemoveButton = false,\n hidePauseButton = false,\n hideCancelButton = false,\n adjustSeconds = 30,\n maxSeconds,\n\n label,\n formatTime = formatTimeDefault,\n size = '160px',\n strokeWidth = 10,\n counterClockwise = false,\n\n urgentThreshold = 0.1,\n urgentMinSeconds = 3,\n pulseOnUrgent = true,\n showRunningRipples = false,\n\n playSoundOnComplete = false,\n soundUrl,\n soundVolume = 0.5,\n notifyOnComplete = false,\n notificationTitle,\n notificationBody,\n\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Timer', props);\n\n const initialMs = durationSeconds * 1000;\n const [status, setStatusState] = useState<TimerStatus>(autoStart ? 'running' : 'idle');\n const [remainingMs, setRemainingMsState] = useState(initialMs);\n const [epoch, setEpoch] = useState(0);\n const [ripples, setRipples] = useState<number[]>([]);\n\n const remainingRef = useRef(remainingMs);\n const statusRef = useRef(status);\n const totalMsRef = useRef(initialMs);\n const completedFiredRef = useRef(false);\n const notifyPermissionRequestedRef = useRef(false);\n const mountedRef = useRef(false);\n const rippleIdRef = useRef(0);\n\n function setRemaining(next: number) {\n remainingRef.current = next;\n setRemainingMsState(next);\n }\n\n function setStatus(next: TimerStatus) {\n statusRef.current = next;\n setStatusState(next);\n }\n\n function bumpEpoch() {\n setEpoch((e) => e + 1);\n }\n\n // Ticking effect. Re-derives the remaining time from Date.now() every tick (rather than\n // accumulating setInterval's own drift), so it stays accurate over long countdowns. Any\n // external mutation of remainingRef (addTime/removeTime while already running, or a resume)\n // must bump `epoch` so this effect re-arms and re-captures a fresh start/startRemaining —\n // without that, a stale `startRemaining` captured before the mutation would silently\n // overwrite it on the next tick.\n useEffect(() => {\n if (status !== 'running') return undefined;\n const start = Date.now();\n const startRemaining = remainingRef.current;\n const id = setInterval(() => {\n const next = Math.max(0, startRemaining - (Date.now() - start));\n setRemaining(next);\n onTick?.(next);\n if (next <= 0) setStatus('completed');\n }, TICK_MS);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status, epoch]);\n\n // Fires onComplete exactly once per completion, plus the opt-in sound/notification.\n useEffect(() => {\n if (status === 'completed' && !completedFiredRef.current) {\n completedFiredRef.current = true;\n onComplete?.();\n if (playSoundOnComplete) {\n try {\n const audio = new Audio(soundUrl || DEFAULT_CHIME_DATA_URI);\n audio.volume = soundVolume;\n // play() can reject (autoplay policy) or, in some environments, return undefined\n // instead of a Promise — never let a blocked/unsupported playback surface as an error.\n audio.play()?.catch(() => {});\n } catch {\n // Audio unavailable/unsupported — fail silently.\n }\n }\n if (notifyOnComplete && typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n try {\n new Notification(notificationTitle ?? 'Timer done', {\n body: notificationBody ?? (typeof label === 'string' ? label : undefined),\n });\n } catch {\n // Some browsers (e.g. certain mobile Safari versions) throw constructing\n // Notification outside specific contexts — fail silently, as documented.\n }\n }\n }\n if (status !== 'completed') completedFiredRef.current = false;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status]);\n\n // durationSeconds prop change: reset (and optionally restart) at the new duration. Skips\n // the initial mount, since autoStart/initial state already cover that.\n useEffect(() => {\n if (!mountedRef.current) {\n mountedRef.current = true;\n return;\n }\n const nextMs = durationSeconds * 1000;\n totalMsRef.current = nextMs;\n setRemaining(nextMs);\n completedFiredRef.current = false;\n bumpEpoch();\n if (resetOnDurationChange) {\n setStatus(autoStart ? 'running' : 'idle');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [durationSeconds]);\n\n // Running-ripple spawner: spawns a new ripple roughly every RIPPLE_SPAWN_INTERVAL_MS while\n // running, each animating once (via CSS, `forwards`) and removing itself on `onAnimationEnd`.\n // Pausing (or otherwise leaving `running`) only stops new spawns here — it doesn't touch\n // `ripples` — so whichever ripples are already mid-flight keep animating to completion\n // instead of vanishing mid-cycle.\n useEffect(() => {\n if (!showRunningRipples || status !== 'running' || prefersReducedMotion()) return undefined;\n function spawnRipple() {\n rippleIdRef.current += 1;\n setRipples((prev) => [...prev, rippleIdRef.current]);\n }\n spawnRipple();\n const id = setInterval(spawnRipple, RIPPLE_SPAWN_INTERVAL_MS);\n return () => clearInterval(id);\n }, [showRunningRipples, status]);\n\n function handleRippleAnimationEnd(id: number) {\n setRipples((prev) => prev.filter((existingId) => existingId !== id));\n }\n\n function requestNotificationPermissionIfNeeded() {\n if (!notifyOnComplete || notifyPermissionRequestedRef.current) return;\n if (typeof Notification === 'undefined' || Notification.permission !== 'default') return;\n notifyPermissionRequestedRef.current = true;\n Notification.requestPermission().catch(() => {});\n }\n\n function start() {\n requestNotificationPermissionIfNeeded();\n if (statusRef.current === 'completed' || statusRef.current === 'cancelled') {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n }\n bumpEpoch();\n setStatus('running');\n onStart?.();\n }\n\n function pause() {\n if (statusRef.current !== 'running') return;\n setStatus('paused');\n onPause?.();\n }\n\n function resume() {\n if (statusRef.current !== 'paused') return;\n bumpEpoch();\n setStatus('running');\n onResume?.();\n }\n\n function addTime(seconds: number) {\n const capped = maxSeconds != null ? maxSeconds * 1000 : Infinity;\n const next = Math.min(remainingRef.current + seconds * 1000, capped);\n setRemaining(next);\n bumpEpoch();\n onAddTime?.(seconds, Math.round(next / 1000));\n if (statusRef.current === 'completed' && next > 0) {\n completedFiredRef.current = false;\n setStatus('running');\n }\n }\n\n function removeTime(seconds: number) {\n const next = Math.max(0, remainingRef.current - seconds * 1000);\n setRemaining(next);\n bumpEpoch();\n onRemoveTime?.(seconds, Math.round(next / 1000));\n if (next <= 0 && statusRef.current === 'running') setStatus('completed');\n }\n\n function cancel() {\n setRemaining(totalMsRef.current);\n setStatus('cancelled');\n onCancel?.();\n }\n\n function reset() {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n setStatus('idle');\n }\n\n useImperativeHandle(ref, () => ({\n start,\n pause,\n resume,\n addTime,\n removeTime,\n cancel,\n reset,\n getStatus: () => statusRef.current,\n getRemainingMs: () => remainingRef.current,\n }));\n\n const radius = 50 - strokeWidth / 2;\n const circumference = useMemo(() => 2 * Math.PI * radius, [radius]);\n const clampedFraction = totalMsRef.current > 0 ? Math.min(1, remainingMs / totalMsRef.current) : 0;\n const dashOffset = circumference * (1 - clampedFraction);\n const urgentMs = Math.max(totalMsRef.current * urgentThreshold, urgentMinSeconds * 1000);\n const isUrgent = status === 'running' && remainingMs <= urgentMs;\n const isCritical = isUrgent && remainingMs <= Math.min(5000, urgentMs);\n const isPaused = status === 'paused';\n\n // The pause button doubles as a play/restart button whenever there's nothing to pause —\n // idle (autoStart={false}), completed, or cancelled — rather than hiding itself, so there's\n // always a way to (re)start the countdown from the built-in controls alone.\n const showAddButton = showControls && !hideAddButton;\n const showRemoveButton = showControls && !hideRemoveButton;\n const showPauseButton = showControls && !hidePauseButton;\n const pauseButtonIcon = status === 'running' ? faPause : faPlay;\n const pauseButtonTitle = status === 'running' ? 'Pause' : isPaused ? 'Resume' : status === 'idle' ? 'Start' : 'Restart';\n const handlePauseButtonClick = status === 'running' ? pause : isPaused ? resume : start;\n const showCancelButton = showControls && !hideCancelButton;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timer,\n pulseOnUrgent && isUrgent && styles.timerPulsing,\n isCritical && styles.timerCritical,\n className,\n classNames?.root,\n )}\n style={{\n '--timer-size': size,\n '--timer-stroke-width': `${strokeWidth}px`,\n ...style,\n ...slotStyles?.root,\n } as React.CSSProperties}\n >\n <div className={cx(styles.timerRingWrapper, classNames?.ringWrapper)} style={slotStyles?.ringWrapper}>\n {ripples.length > 0 && (\n <div className={cx(styles.timerRipples, classNames?.ripples)} style={slotStyles?.ripples}>\n {ripples.map((id) => (\n <span\n key={id}\n className={cx(styles.timerRipple, classNames?.ripple)}\n style={slotStyles?.ripple}\n onAnimationEnd={() => handleRippleAnimationEnd(id)}\n />\n ))}\n </div>\n )}\n <svg\n className={cx(styles.timerRingSvg, classNames?.ringSvg)}\n viewBox=\"0 0 100 100\"\n style={slotStyles?.ringSvg}\n >\n <circle\n className={cx(styles.timerRingTrack, classNames?.ringTrack)}\n cx=\"50\"\n cy=\"50\"\n r={radius}\n style={slotStyles?.ringTrack}\n />\n <circle\n className={cx(styles.timerRingProgress, isUrgent && styles.timerRingProgressUrgent, classNames?.ringProgress)}\n cx=\"50\"\n cy=\"50\"\n r={radius}\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n style={{\n transition: isPaused ? 'none' : undefined,\n transform: counterClockwise ? 'rotate(-90deg)' : undefined,\n ...slotStyles?.ringProgress,\n }}\n />\n </svg>\n <div className={cx(styles.timerDisplay, classNames?.display)} style={slotStyles?.display}>\n <span className={cx(styles.timerTime, classNames?.time)} style={slotStyles?.time}>\n {formatTime(remainingMs)}\n </span>\n {label && (\n <span className={cx(styles.timerLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n </span>\n )}\n </div>\n </div>\n\n {showControls && (\n <div className={cx(styles.timerControls, classNames?.controls)} style={slotStyles?.controls}>\n <div className={styles.timerControlsRow}>\n {showRemoveButton && (\n <ActionIcon\n icon={faMinus}\n title={`Remove ${adjustSeconds}s`}\n onClick={() => removeTime(adjustSeconds)}\n className={cx(styles.timerAdjustButton, classNames?.removeButton)}\n style={slotStyles?.removeButton}\n />\n )}\n {showPauseButton && (\n <Button\n size={ButtonSize.Small}\n icon={pauseButtonIcon}\n title={pauseButtonTitle}\n onClick={handlePauseButtonClick}\n className={classNames?.pauseButton}\n style={slotStyles?.pauseButton}\n />\n )}\n {showAddButton && (\n <ActionIcon\n icon={faPlus}\n title={`Add ${adjustSeconds}s`}\n onClick={() => addTime(adjustSeconds)}\n className={cx(styles.timerAdjustButton, classNames?.addButton)}\n style={slotStyles?.addButton}\n />\n )}\n </div>\n {showCancelButton && (\n <ActionIcon\n icon={faXmark}\n title=\"Cancel timer\"\n onClick={cancel}\n className={cx(styles.timerCancelButton, classNames?.cancelButton)}\n style={slotStyles?.cancelButton}\n />\n )}\n </div>\n )}\n </div>\n );\n});\n\nTimer.displayName = 'Timer';\n\nexport default Timer;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(t,n,r=0,i=null){return t.flatMap((a,o)=>{let s=a.children!==void 0,c=s&&n.includes(a.key),l={node:a,level:r,parentKey:i,isBranch:s,isExpanded:c,setSize:t.length,posInSet:o+1};return!c||!a.children?.length?[l]:[l,...e(a.children,n,r+1,a.key)]})}export{e as flattenTree};
|
|
2
|
+
//# sourceMappingURL=flattenTree.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flattenTree.mjs","names":[],"sources":["../../../../package/common/tree/flattenTree.ts"],"sourcesContent":["import type { FlatTreeNode, TreeNode, TreeValue } from './tree.types';\n\n/** The visible nodes in render order. Flat, not nested, deliberately: see docs/Tree.md. */\nexport function flattenTree(\n nodes: TreeNode[],\n expandedKeys: TreeValue[],\n level = 0,\n parentKey: TreeValue | null = null\n): FlatTreeNode[] {\n return nodes.flatMap((node, index) => {\n const isBranch = node.children !== undefined;\n const isExpanded = isBranch && expandedKeys.includes(node.key);\n const self: FlatTreeNode = {\n node,\n level,\n parentKey,\n isBranch,\n isExpanded,\n setSize: nodes.length,\n posInSet: index + 1,\n };\n if (!isExpanded || !node.children?.length) return [self];\n return [self, ...flattenTree(node.children, expandedKeys, level + 1, node.key)];\n });\n}\n"],"mappings":"AAGA,SAAgB,EACd,EACA,EACA,EAAQ,EACR,EAA8B,KACd,CAChB,OAAO,EAAM,SAAS,EAAM,IAAU,CACpC,IAAM,EAAW,EAAK,WAAa,IAAA,GAC7B,EAAa,GAAY,EAAa,SAAS,EAAK,GAAG,EACvD,EAAqB,CACzB,OACA,QACA,YACA,WACA,aACA,QAAS,EAAM,OACf,SAAU,EAAQ,CACpB,EAEA,MADI,CAAC,GAAc,CAAC,EAAK,UAAU,OAAe,CAAC,CAAI,EAChD,CAAC,EAAM,GAAG,EAAY,EAAK,SAAU,EAAc,EAAQ,EAAG,EAAK,GAAG,CAAC,CAChF,CAAC,CACH"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"../virtualList/virtualList.mjs";import{flattenTree as r}from"./flattenTree.mjs";import i from"./tree.module.mjs";import{useEffect as a,useRef as o,useState as s}from"react";import c from"classnames";import{faChevronRight as l}from"@fortawesome/free-solid-svg-icons";import{jsx as u,jsxs as d}from"react/jsx-runtime";var f=[];function p(p){let{nodes:m,expandedKeys:h,defaultExpandedKeys:g=f,onExpandedChange:_=()=>{},selectedKey:v,defaultSelectedKey:y,onSelect:b=()=>{},expandOnSelect:x=!0,indent:S=20,toggleIcon:C=l,height:w,estimatedRowHeight:T=32,emptyLabel:ee=`Nothing here`,disabled:E=!1,"aria-label":D=`Tree`,className:O,style:k,classNames:A,styles:j,...M}=e(`Tree`,p),N=o(new Map),P=o(null),F=o(null),I=w!==void 0,L=h!==void 0,[R,z]=s(g),B=L?h:R,V=v!==void 0,[H,U]=s(y??null),W=V?v:H,G=r(m,B),K=Math.max(0,G.findIndex(e=>e.node.key===W)),q=G[K]?.node.key;function J(e){L||z(e),_(e)}function Y(e){J(B.includes(e)?B.filter(t=>t!==e):[...B,e])}function X(e){E||e.node.disabled||(V||U(e.node.key),b(e.node.key,e.node),x&&e.isBranch&&Y(e.node.key))}function Z(e){let t=G[e]?.node.key;if(t===void 0)return;let n=N.current.get(t);if(n){n.focus();return}F.current=t,P.current?.scrollToIndex(e,{align:`center`})}a(()=>{let e=F.current;if(e===null)return;let t=N.current.get(e);t&&(t.focus(),F.current=null)});function Q(e,t,n){if(!E)switch(e.key){case`ArrowDown`:e.preventDefault(),Z(Math.min(n+1,G.length-1));break;case`ArrowUp`:e.preventDefault(),Z(Math.max(n-1,0));break;case`ArrowRight`:if(e.preventDefault(),!t.isBranch)break;t.isExpanded?Z(n+1):Y(t.node.key);break;case`ArrowLeft`:{if(e.preventDefault(),t.isBranch&&t.isExpanded){Y(t.node.key);break}let n=G.findIndex(e=>e.node.key===t.parentKey);n>=0&&Z(n);break}case`Home`:e.preventDefault(),Z(0);break;case`End`:e.preventDefault(),Z(G.length-1);break;case`Enter`:case` `:e.preventDefault(),X(t);break;default:break}}function $(e,n){let{node:r,level:a,isBranch:o,isExpanded:s}=e,l=r.key===W,f=E||r.disabled;return d(`div`,{ref:e=>{e?N.current.set(r.key,e):N.current.delete(r.key)},role:`treeitem`,"aria-level":a+1,"aria-setsize":e.setSize,"aria-posinset":e.posInSet,"aria-expanded":o?s:void 0,"aria-selected":l,"aria-disabled":f||void 0,tabIndex:r.key===q&&!f?0:-1,className:c(i.treeNode,l&&i.treeNodeSelected,f&&i.treeNodeDisabled,A?.node),style:{paddingLeft:a*S,...j?.node},onClick:()=>X(e),onKeyDown:t=>Q(t,e,n),children:[u(`span`,{className:c(i.treeToggle,s&&i.treeToggleOpen,!o&&i.treeToggleHidden,A?.toggle),style:j?.toggle,"aria-hidden":`true`,onClick:e=>{e.stopPropagation(),!f&&o&&Y(r.key)},children:o&&t(C)}),r.icon&&t(r.icon,{className:c(i.treeIcon,A?.icon),style:j?.icon}),u(`span`,{className:c(i.treeLabel,A?.label),style:j?.label,children:r.label})]},r.key)}return u(`div`,{...M,role:`tree`,"aria-label":D,"aria-disabled":E||void 0,tabIndex:I&&!E?0:void 0,onFocus:e=>{e.target===e.currentTarget&&Z(K)},className:c(i.tree,E&&i.treeDisabled,A?.root,O),style:{...k,...j?.root},children:G.length===0?u(`div`,{className:c(i.treeEmpty,A?.empty),style:j?.empty,children:ee}):I?u(n,{ref:P,items:G,height:w,estimatedRowHeight:T,getItemKey:e=>e.node.key,getItemDepth:e=>e.level,ariaRoles:{container:`none`,row:`none`},renderRow:$}):G.map($)})}export{p as default};
|
|
2
|
+
//# sourceMappingURL=tree.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.mjs","names":[],"sources":["../../../../package/common/tree/tree.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport VirtualList from 'components/common/virtualList';\nimport type { VirtualListHandle } from 'components/common/virtualList';\nimport { useComponentDefaults } from '../configProvider';\nimport { renderIcon } from '../utils/renderIcon';\nimport { flattenTree } from './flattenTree';\nimport type { FlatTreeNode, TreeProps, TreeValue } from './tree.types';\n\nimport styles from './tree.module.pcss';\n\nconst EMPTY_KEYS: TreeValue[] = [];\n\nfunction Tree(props: TreeProps): ReactElement {\n const {\n nodes,\n expandedKeys: controlledExpanded,\n defaultExpandedKeys = EMPTY_KEYS,\n onExpandedChange = () => {},\n selectedKey: controlledSelected,\n defaultSelectedKey,\n onSelect = () => {},\n expandOnSelect = true,\n indent = 20,\n toggleIcon = faChevronRight,\n height,\n estimatedRowHeight = 32,\n emptyLabel = 'Nothing here',\n disabled = false,\n 'aria-label': ariaLabel = 'Tree',\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Tree', props);\n\n const nodeRefs = useRef(new Map<TreeValue, HTMLDivElement>());\n const listRef = useRef<VirtualListHandle>(null);\n const pendingFocusRef = useRef<TreeValue | null>(null);\n const isWindowed = height !== undefined;\n\n const isExpandedControlled = controlledExpanded !== undefined;\n const [internalExpanded, setInternalExpanded] = useState<TreeValue[]>(defaultExpandedKeys);\n const expandedKeys = isExpandedControlled ? controlledExpanded : internalExpanded;\n\n const isSelectedControlled = controlledSelected !== undefined;\n const [internalSelected, setInternalSelected] = useState<TreeValue | null>(defaultSelectedKey ?? null);\n const selectedKey = isSelectedControlled ? controlledSelected : internalSelected;\n\n const visible = flattenTree(nodes, expandedKeys);\n\n // Windowed, the tab stop sits on the container instead of this row: a roving tabindex on a row\n // scrolled out of the window would leave the tree with no tab stop at all.\n const activeIndex = Math.max(0, visible.findIndex((entry) => entry.node.key === selectedKey));\n const activeKey = visible[activeIndex]?.node.key;\n\n function setExpanded(next: TreeValue[]) {\n if (!isExpandedControlled) setInternalExpanded(next);\n onExpandedChange(next);\n }\n\n function toggle(key: TreeValue) {\n setExpanded(\n expandedKeys.includes(key) ? expandedKeys.filter((k) => k !== key) : [...expandedKeys, key]\n );\n }\n\n function select(entry: FlatTreeNode) {\n if (disabled || entry.node.disabled) return;\n if (!isSelectedControlled) setInternalSelected(entry.node.key);\n onSelect(entry.node.key, entry.node);\n if (expandOnSelect && entry.isBranch) toggle(entry.node.key);\n }\n\n function focusAt(index: number) {\n const key = visible[index]?.node.key;\n if (key === undefined) return;\n\n const element = nodeRefs.current.get(key);\n if (element) {\n element.focus();\n return;\n }\n\n // Outside the window, so it has to be scrolled in before it exists to receive focus.\n pendingFocusRef.current = key;\n listRef.current?.scrollToIndex(index, { align: 'center' });\n }\n\n useEffect(() => {\n const key = pendingFocusRef.current;\n if (key === null) return;\n const element = nodeRefs.current.get(key);\n if (element) {\n element.focus();\n pendingFocusRef.current = null;\n }\n });\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>, entry: FlatTreeNode, index: number) {\n if (disabled) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusAt(Math.min(index + 1, visible.length - 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusAt(Math.max(index - 1, 0));\n break;\n case 'ArrowRight':\n event.preventDefault();\n if (!entry.isBranch) break;\n if (entry.isExpanded) focusAt(index + 1);\n else toggle(entry.node.key);\n break;\n case 'ArrowLeft': {\n event.preventDefault();\n if (entry.isBranch && entry.isExpanded) {\n toggle(entry.node.key);\n break;\n }\n const parentIndex = visible.findIndex((e) => e.node.key === entry.parentKey);\n if (parentIndex >= 0) focusAt(parentIndex);\n break;\n }\n case 'Home':\n event.preventDefault();\n focusAt(0);\n break;\n case 'End':\n event.preventDefault();\n focusAt(visible.length - 1);\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n select(entry);\n break;\n default:\n break;\n }\n }\n\n function renderNode(entry: FlatTreeNode, index: number) {\n const { node, level, isBranch, isExpanded } = entry;\n const isSelected = node.key === selectedKey;\n const isDisabled = disabled || node.disabled;\n\n return (\n <div\n key={node.key}\n ref={(el) => {\n if (el) nodeRefs.current.set(node.key, el);\n else nodeRefs.current.delete(node.key);\n }}\n role=\"treeitem\"\n aria-level={level + 1}\n aria-setsize={entry.setSize}\n aria-posinset={entry.posInSet}\n aria-expanded={isBranch ? isExpanded : undefined}\n aria-selected={isSelected}\n aria-disabled={isDisabled || undefined}\n tabIndex={node.key === activeKey && !isDisabled ? 0 : -1}\n className={cx(\n styles.treeNode,\n isSelected && styles.treeNodeSelected,\n isDisabled && styles.treeNodeDisabled,\n classNames?.node\n )}\n style={{ paddingLeft: level * indent, ...slotStyles?.node }}\n onClick={() => select(entry)}\n onKeyDown={(event) => handleKeyDown(event, entry, index)}\n >\n <span\n className={cx(\n styles.treeToggle,\n isExpanded && styles.treeToggleOpen,\n !isBranch && styles.treeToggleHidden,\n classNames?.toggle\n )}\n style={slotStyles?.toggle}\n aria-hidden=\"true\"\n onClick={(event) => {\n event.stopPropagation();\n if (!isDisabled && isBranch) toggle(node.key);\n }}\n >\n {isBranch && renderIcon(toggleIcon)}\n </span>\n\n {node.icon &&\n renderIcon(node.icon, {\n className: cx(styles.treeIcon, classNames?.icon),\n style: slotStyles?.icon,\n })}\n\n <span className={cx(styles.treeLabel, classNames?.label)} style={slotStyles?.label}>\n {node.label}\n </span>\n </div>\n );\n }\n\n return (\n <div\n {...rest}\n role=\"tree\"\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n tabIndex={isWindowed && !disabled ? 0 : undefined}\n onFocus={(event) => {\n if (event.target === event.currentTarget) focusAt(activeIndex);\n }}\n className={cx(styles.tree, disabled && styles.treeDisabled, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {visible.length === 0 ? (\n <div className={cx(styles.treeEmpty, classNames?.empty)} style={slotStyles?.empty}>\n {emptyLabel}\n </div>\n ) : isWindowed ? (\n <VirtualList\n ref={listRef}\n items={visible}\n height={height}\n estimatedRowHeight={estimatedRowHeight}\n getItemKey={(entry) => entry.node.key}\n getItemDepth={(entry) => entry.level}\n ariaRoles={{ container: 'none', row: 'none' }}\n renderRow={renderNode}\n />\n ) : (\n visible.map(renderNode)\n )}\n </div>\n );\n}\n\nexport default Tree;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e={tree:`tree_bHT4K`,"tree-disabled":`tree-disabled_bIFfs`,treeDisabled:`tree-disabled_bIFfs`,"tree-node":`tree-node_XUWMs`,treeNode:`tree-node_XUWMs`,"tree-node-selected":`tree-node-selected_j05ku`,treeNodeSelected:`tree-node-selected_j05ku`,"tree-node-disabled":`tree-node-disabled_FMox6`,treeNodeDisabled:`tree-node-disabled_FMox6`,"tree-toggle":`tree-toggle_hmqtx`,treeToggle:`tree-toggle_hmqtx`,"tree-toggle-open":`tree-toggle-open_gTfYS`,treeToggleOpen:`tree-toggle-open_gTfYS`,"tree-toggle-hidden":`tree-toggle-hidden_nYrlV`,treeToggleHidden:`tree-toggle-hidden_nYrlV`,"tree-icon":`tree-icon_0dxsy`,treeIcon:`tree-icon_0dxsy`,"tree-label":`tree-label_BOShA`,treeLabel:`tree-label_BOShA`,"tree-empty":`tree-empty_Eb3vv`,treeEmpty:`tree-empty_Eb3vv`};export{e as default};
|
|
2
|
+
//# sourceMappingURL=tree.module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.module.mjs","names":[],"sources":["../../../../package/common/tree/tree.module.pcss"],"sourcesContent":[".tree {\n display: flex;\n flex-direction: column;\n width: 100%;\n color: var(--text-color);\n\n &-disabled {\n opacity: 0.5;\n }\n\n &-node {\n display: flex;\n align-items: center;\n gap: 6px;\n box-sizing: border-box;\n min-height: var(--tree-node-height, 32px);\n padding-right: 8px;\n border-radius: var(--default-border-radius);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n user-select: none;\n\n &:hover {\n background: var(--background-accent);\n }\n\n &:focus-visible {\n outline: var(--focus-border-color, var(--primary-color)) solid 2px;\n outline-offset: -2px;\n }\n\n &-selected {\n background: var(--tree-selected-background, var(--primary-color));\n color: var(--tree-selected-color, var(--text-on-primary));\n\n &:hover {\n background: var(--tree-selected-background, var(--primary-color));\n }\n\n &:focus-visible {\n outline-color: var(--tree-selected-color, var(--text-on-primary));\n }\n }\n\n &-disabled {\n opacity: 0.5;\n cursor: default;\n\n &:hover {\n background: transparent;\n }\n }\n }\n\n &-toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 1.25em;\n height: 1.25em;\n font-size: 0.8em;\n border-radius: 50%;\n transition: transform 0.15s;\n\n &-open {\n transform: rotate(90deg);\n }\n\n /* Kept in the layout rather than removed, so leaf labels line up with their siblings'. */\n &-hidden {\n visibility: hidden;\n }\n }\n\n &-icon {\n flex: none;\n width: 1em;\n }\n\n &-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &-empty {\n padding: 12px 8px;\n color: var(--text-dark);\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"../loading/spinnerLoading/index.mjs";import{Align as t}from"../floatingMenu/floatingMenu.types.mjs";import n from"../floatingMenu/floatingMenu.mjs";import r from"../checkbox/checkbox.mjs";import i from"./virtualList.module.mjs";import
|
|
1
|
+
import e from"../loading/spinnerLoading/index.mjs";import{Align as t}from"../floatingMenu/floatingMenu.types.mjs";import n from"../floatingMenu/floatingMenu.mjs";import r from"../checkbox/checkbox.mjs";import i from"./virtualList.module.mjs";import a from"./virtualRow.mjs";import"./virtualList.utils.mjs";import{useVirtualWindow as o}from"./useVirtualWindow.mjs";import{useSelection as s}from"./useSelection.mjs";import{useColumns as ee}from"./useColumns.mjs";import{useRowDrag as te}from"./useRowDrag.mjs";import c,{useCallback as l,useImperativeHandle as ne,useMemo as u}from"react";import d from"classnames";import{FontAwesomeIcon as f}from"@fortawesome/react-fontawesome";import{faGear as re}from"@fortawesome/free-solid-svg-icons";import{Fragment as ie,jsx as p,jsxs as m}from"react/jsx-runtime";function h({items:c,renderRow:h,ariaRoles:g,columns:_,height:v=`100%`,estimatedRowHeight:ae=40,overscan:oe=3,rowGap:se=0,rowPadding:y,selectedKey:b,getItemKey:x,onRowClick:ce,visibleColumnKeys:le,onVisibleColumnsChange:ue,persistColumnsKey:de,showColumnToggle:fe,onLoadMore:pe,loadMoreThreshold:me=100,isLoading:S=!1,multiSelect:C=!1,selectedKeys:he,onSelectionChange:ge,reorderable:_e=!1,onReorder:ve,longPressDelay:ye=400,treeReorder:be=!1,getItemDepth:w,isGroup:T,onTreeDrop:E,treeIndentPx:D=24,dragHandle:O=!1,showDivider:k=!0,rowHover:A=!0,className:j,style:M,classNames:N,styles:P,...xe},Se){let F=l((e,t)=>x?x(e,t):t,[x]),I=u(()=>c.map((e,t)=>F(e,t)),[c,F]),Ce=u(()=>w?c.map((e,t)=>w(e,t)):[],[c,w]),we=l(e=>T?T(c[e],e):!1,[T,c]),L=o({items:c,keys:I,getItemKey:x,estimatedRowHeight:ae,rowGap:se,overscan:oe,onLoadMore:pe,loadMoreThreshold:me,isLoading:S}),{rootRef:R,headerRef:Te,rowObserver:Ee,keysRef:De,offsets:Oe,totalHeight:ke,startIndex:z,endIndex:B}=L,V=s({items:c,getKey:F,multiSelect:C,selectedKeys:he,onSelectionChange:ge}),{effectiveSelectedKeys:H}=V,{hasColumns:U,visibleColumns:W,columnTemplate:G,shouldShowToggle:K,effectiveVisible:Ae,manuallyHiddenCount:q,toggleOpen:je,setToggleOpen:Me,handleToggleColumn:J,recalculateColumns:Y}=ee({columns:_,items:c,multiSelect:C,visibleColumnKeys:le,onVisibleColumnsChange:ue,persistColumnsKey:de,showColumnToggle:fe,rootRef:R,startIndex:z,endIndex:B,containerHeight:L.containerHeight,containerWidth:L.containerWidth});ne(Se,()=>({...L.scrollApi,recalculateColumns:Y}),[L.scrollApi,Y]);let X=te({reorderable:_e,treeReorder:be,onReorder:ve,onTreeDrop:E,longPressDelay:ye,dragHandle:O,treeIndentPx:D,keys:I,depths:Ce,isGroupAt:we,rootRef:R,keysRef:De}),Ne=typeof y==`number`?`${y}px`:y,Z=e=>{let t=c[e],n=F(t,e),o=b!=null&&n===b||H.has(n),s=X.getRowDragProps(e,n);return p(a,{index:e,top:Oe[e],padding:Ne,columnTemplate:G,isSelected:o,showDivider:k,hover:A,onClick:()=>{X.consumeSuppressedClick()||ce?.(t,e)},observer:Ee,ariaRowIndex:U?e+2:void 0,ariaPosInSet:U?void 0:e+1,ariaSetSize:U?void 0:c.length,rowRole:g?.row??(U?`row`:`listitem`),reserveToggleGutter:K,...s,dropIndicatorClassName:N?.dropIndicator,dropIndicatorStyle:P?.dropIndicator,rowClassName:N?.row,rowStyle:P?.row,children:U?m(ie,{children:[C&&p(`div`,{className:d(i.virtualListSelectCell,N?.selectCell),style:P?.selectCell,role:`gridcell`,onClick:e=>e.stopPropagation(),children:p(r,{selected:H.has(n),onToggle:()=>V.handleRowSelect(n),"aria-label":`Select row`})}),W.map(n=>p(`div`,{className:d(i.virtualListCell,N?.cell),style:P?.cell,role:`gridcell`,"data-fit-key":n.width.type===`fit`?n.key:void 0,children:n.renderCell(t,e)},n.key))]}):h?.(t,e)},n)},Q=[];for(let e=z;e<=B;e++)Q.push(Z(e));let $=X.draggingKey==null?-1:I.indexOf(X.draggingKey);return $>=0&&($<z||$>B)&&Q.push(Z($)),m(`div`,{...xe,ref:R,className:d(i.virtualList,X.draggingKey!=null&&i.virtualListReordering,j,N?.root),style:{height:v,...M,...P?.root},onScroll:L.handleScroll,role:g?.container??(U?`grid`:`list`),"aria-rowcount":U?c.length+1:void 0,children:[U&&m(`div`,{ref:Te,className:d(i.virtualListHeader,N?.header),style:{gridTemplateColumns:G,...K?{paddingRight:32}:{},...P?.header},role:`row`,"aria-rowindex":1,children:[C&&p(`div`,{className:d(i.virtualListSelectCell,N?.selectCell),style:P?.selectCell,role:`columnheader`,children:p(r,{selected:V.allSelected||V.someSelected,onToggle:V.handleSelectAll,"aria-label":`Select all rows`})}),W.map(e=>p(`div`,{className:d(i.virtualListHeaderCell,N?.headerCell),style:P?.headerCell,role:`columnheader`,"data-fit-key":e.width.type===`fit`?e.key:void 0,children:e.label},e.key)),K&&m(`div`,{className:i.virtualListToggleWrapper,children:[p(n,{isOpen:je,onOpenChange:Me,align:t.Right,dontCloseOnChildClick:!0,content:p(`div`,{className:d(i.virtualListTogglePopover,N?.togglePopover),style:P?.togglePopover,children:_.filter(e=>!e.hideFromToggle).map(e=>p(r,{className:d(i.virtualListToggleItem,N?.toggleItem),style:P?.toggleItem,selected:Ae.has(e.key),onToggle:()=>J(e.key),disabled:e.lockVisible,cursorDefault:!1,children:e.toggleLabel??e.label},e.key))}),children:p(`button`,{type:`button`,className:d(i.virtualListHeaderToggle,N?.headerToggle),style:P?.headerToggle,"aria-label":`Toggle column visibility`,children:p(f,{icon:re,style:P?.headerToggle})})}),q>0&&p(`span`,{className:d(i.virtualListColumnChip,N?.columnChip),style:P?.columnChip,"data-column-hidden-count":q,"aria-label":`${q} columns hidden`,children:q})]})]}),S?p(`div`,{className:i.virtualListLoadingFull,children:p(e,{className:i.virtualListSpinner})}):p(`div`,{className:d(i.virtualListBody,N?.body),style:{height:ke,...P?.body},children:Q}),L.showLoadMoreSpinner&&p(`div`,{className:d(i.virtualListLoadingIndicator,N?.loadingIndicator),style:P?.loadingIndicator,children:p(e,{className:i.virtualListSpinner})})]})}var g=c.forwardRef(h);export{g as default};
|
|
2
2
|
//# sourceMappingURL=virtualList.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualList.mjs","names":[],"sources":["../../../../package/common/virtualList/virtualList.tsx"],"sourcesContent":["import React, { useMemo, useCallback, useImperativeHandle } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faGear } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './virtualList.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport Checkbox from '../checkbox';\nimport FloatingMenu, { Align } from '../floatingMenu';\nimport VirtualRow from './virtualRow';\nimport { useVirtualWindow } from './useVirtualWindow';\nimport { useSelection } from './useSelection';\nimport { useColumns } from './useColumns';\nimport { useRowDrag } from './useRowDrag';\nimport type { VirtualListProps, VirtualListHandle } from './virtualList.types';\n\n// Pure helpers live in ./virtualList.utils; re-exported here so existing\n// imports (and unit tests) keep working against the component entry point.\nexport {\n buildOffsets,\n findStartIndex,\n getVisibleRange,\n resolveReorderTarget,\n resolveTreeDropTarget,\n lastDescendantIndex,\n buildColumnTemplate,\n} from './virtualList.utils';\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n// VirtualListInner wires four focused hooks together and renders. Each concern\n// lives in its own module:\n// useVirtualWindow — generic scroll / measurement / windowing (all modes)\n// useSelection — multi-row selection\n// useColumns — table mode: columns, visibility, persistence, fit widths\n// useRowDrag — reorder + tree drag-and-drop (mouse + touch)\n\nfunction VirtualListInner<T>({\n items,\n renderRow,\n columns,\n height = '100%',\n estimatedRowHeight = 40,\n overscan = 3,\n rowGap = 0,\n rowPadding,\n selectedKey,\n getItemKey,\n onRowClick,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n onLoadMore,\n loadMoreThreshold = 100,\n isLoading = false,\n multiSelect = false,\n selectedKeys,\n onSelectionChange,\n reorderable = false,\n onReorder,\n longPressDelay = 400,\n treeReorder = false,\n getItemDepth,\n isGroup,\n onTreeDrop,\n treeIndentPx = 24,\n dragHandle = false,\n showDivider = true,\n rowHover = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: VirtualListProps<T>, ref: React.ForwardedRef<VirtualListHandle>) {\n const getKey = useCallback(\n (item: T, index: number): string | number => (getItemKey ? getItemKey(item, index) : index),\n [getItemKey],\n );\n const keys = useMemo(() => items.map((item, i) => getKey(item, i)), [items, getKey]);\n const depths = useMemo(\n () => (getItemDepth ? items.map((item, i) => getItemDepth(item, i)) : []),\n [items, getItemDepth],\n );\n const isGroupAt = useCallback(\n (i: number) => (isGroup ? isGroup(items[i], i) : false),\n [isGroup, items],\n );\n\n const win = useVirtualWindow<T>({\n items, keys, getItemKey, estimatedRowHeight, rowGap, overscan,\n onLoadMore, loadMoreThreshold, isLoading,\n });\n const { rootRef, headerRef, rowObserver, keysRef, offsets, totalHeight, startIndex, endIndex } = win;\n\n const selection = useSelection<T>({ items, getKey, multiSelect, selectedKeys, onSelectionChange });\n const { effectiveSelectedKeys } = selection;\n\n const cols = useColumns<T>({\n columns, items, multiSelect, visibleColumnKeys, onVisibleColumnsChange, persistColumnsKey,\n showColumnToggle, rootRef, startIndex, endIndex,\n containerHeight: win.containerHeight, containerWidth: win.containerWidth,\n });\n const {\n hasColumns, visibleColumns, columnTemplate, shouldShowToggle, effectiveVisible, manuallyHiddenCount,\n toggleOpen, setToggleOpen, handleToggleColumn, recalculateColumns,\n } = cols;\n\n // Compose the forwarded handle from both hooks: scroll methods come from the\n // windowing engine, column controls from the column hook.\n useImperativeHandle(\n ref,\n () => ({ ...win.scrollApi, recalculateColumns }),\n [win.scrollApi, recalculateColumns],\n );\n\n const drag = useRowDrag({\n reorderable, treeReorder, onReorder, onTreeDrop, longPressDelay, dragHandle, treeIndentPx,\n keys, depths, isGroupAt, rootRef, keysRef,\n });\n\n const rowPaddingValue = typeof rowPadding === 'number' ? `${rowPadding}px` : rowPadding;\n\n const renderRowAt = (i: number) => {\n const item = items[i];\n const key = getKey(item, i);\n const isSelected = (selectedKey != null && key === selectedKey) || effectiveSelectedKeys.has(key);\n const dragProps = drag.getRowDragProps(i, key);\n\n return (\n <VirtualRow\n key={key}\n index={i}\n top={offsets[i]}\n padding={rowPaddingValue}\n columnTemplate={columnTemplate}\n isSelected={isSelected}\n showDivider={showDivider}\n hover={rowHover}\n onClick={() => {\n if (drag.consumeSuppressedClick()) return;\n onRowClick?.(item, i);\n }}\n observer={rowObserver}\n ariaRowIndex={hasColumns ? i + 2 : undefined}\n ariaPosInSet={hasColumns ? undefined : i + 1}\n ariaSetSize={hasColumns ? undefined : items.length}\n rowRole={hasColumns ? 'row' : 'listitem'}\n reserveToggleGutter={shouldShowToggle}\n {...dragProps}\n dropIndicatorClassName={classNames?.dropIndicator}\n dropIndicatorStyle={slotStyles?.dropIndicator}\n rowClassName={classNames?.row}\n rowStyle={slotStyles?.row}\n >\n {hasColumns\n ? <>\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"gridcell\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n selected={effectiveSelectedKeys.has(key)}\n onToggle={() => selection.handleRowSelect(key)}\n aria-label=\"Select row\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListCell, classNames?.cell)}\n style={slotStyles?.cell}\n role=\"gridcell\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.renderCell(item, i)}\n </div>\n ))}\n </>\n : renderRow?.(item, i)}\n </VirtualRow>\n );\n };\n\n const visibleRows: React.ReactNode[] = [];\n for (let i = startIndex; i <= endIndex; i++) visibleRows.push(renderRowAt(i));\n\n // Keep the row being touch-dragged mounted even if it scrolls out of the\n // window. Touch events are dispatched to the element under the finger at\n // touchstart; if that row unmounts, the browser stops delivering touchmove\n // and the drag freezes. Pinning its DOM node keeps the gesture alive.\n const draggedIndex = drag.draggingKey != null ? keys.indexOf(drag.draggingKey) : -1;\n if (draggedIndex >= 0 && (draggedIndex < startIndex || draggedIndex > endIndex)) {\n visibleRows.push(renderRowAt(draggedIndex));\n }\n\n return (\n <div\n {...rest}\n ref={rootRef}\n className={cx(styles.virtualList, drag.draggingKey != null && styles.virtualListReordering, className, classNames?.root)}\n style={{ height, ...style, ...slotStyles?.root }}\n onScroll={win.handleScroll}\n role={hasColumns ? 'grid' : 'list'}\n aria-rowcount={hasColumns ? items.length + 1 : undefined}\n >\n {hasColumns && (\n <div\n ref={headerRef}\n className={cx(styles.virtualListHeader, classNames?.header)}\n style={{ gridTemplateColumns: columnTemplate, ...(shouldShowToggle ? { paddingRight: 32 } : {}), ...slotStyles?.header }}\n role=\"row\"\n aria-rowindex={1}\n >\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"columnheader\"\n >\n <Checkbox\n selected={selection.allSelected || selection.someSelected}\n onToggle={selection.handleSelectAll}\n aria-label=\"Select all rows\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListHeaderCell, classNames?.headerCell)}\n style={slotStyles?.headerCell}\n role=\"columnheader\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.label}\n </div>\n ))}\n {shouldShowToggle && (\n <div className={styles.virtualListToggleWrapper}>\n <FloatingMenu\n isOpen={toggleOpen}\n onOpenChange={setToggleOpen}\n align={Align.Right}\n dontCloseOnChildClick\n content={\n <div\n className={cx(styles.virtualListTogglePopover, classNames?.togglePopover)}\n style={slotStyles?.togglePopover}\n >\n {columns!.filter((col) => !col.hideFromToggle).map((col) => (\n <Checkbox\n key={col.key}\n className={cx(styles.virtualListToggleItem, classNames?.toggleItem)}\n style={slotStyles?.toggleItem}\n selected={effectiveVisible.has(col.key)}\n onToggle={() => handleToggleColumn(col.key)}\n disabled={col.lockVisible}\n cursorDefault={false}\n >\n {col.toggleLabel ?? col.label}\n </Checkbox>\n ))}\n </div>\n }\n >\n <button\n type=\"button\"\n className={cx(styles.virtualListHeaderToggle, classNames?.headerToggle)}\n style={slotStyles?.headerToggle}\n aria-label=\"Toggle column visibility\"\n >\n <FontAwesomeIcon\n icon={faGear}\n style={slotStyles?.headerToggle as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </button>\n </FloatingMenu>\n {manuallyHiddenCount > 0 && (\n <span\n className={cx(styles.virtualListColumnChip, classNames?.columnChip)}\n style={slotStyles?.columnChip}\n data-column-hidden-count={manuallyHiddenCount}\n aria-label={`${manuallyHiddenCount} columns hidden`}\n >\n {manuallyHiddenCount}\n </span>\n )}\n </div>\n )}\n </div>\n )}\n {isLoading ? (\n <div className={styles.virtualListLoadingFull}>\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n ) : (\n <div\n className={cx(styles.virtualListBody, classNames?.body)}\n style={{ height: totalHeight, ...slotStyles?.body }}\n >\n {visibleRows}\n </div>\n )}\n {win.showLoadMoreSpinner && (\n <div\n className={cx(styles.virtualListLoadingIndicator, classNames?.loadingIndicator)}\n style={slotStyles?.loadingIndicator}\n >\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n )}\n </div>\n );\n}\n\n// forwardRef erases the generic, so cast back to a generic-preserving signature.\nconst VirtualList = React.forwardRef(VirtualListInner) as <T>(\n props: VirtualListProps<T> & { ref?: React.Ref<VirtualListHandle> },\n) => React.ReactElement | null;\n\nexport default VirtualList;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"virtualList.mjs","names":[],"sources":["../../../../package/common/virtualList/virtualList.tsx"],"sourcesContent":["import React, { useMemo, useCallback, useImperativeHandle } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faGear } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './virtualList.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport Checkbox from '../checkbox';\nimport FloatingMenu, { Align } from '../floatingMenu';\nimport VirtualRow from './virtualRow';\nimport { useVirtualWindow } from './useVirtualWindow';\nimport { useSelection } from './useSelection';\nimport { useColumns } from './useColumns';\nimport { useRowDrag } from './useRowDrag';\nimport type { VirtualListProps, VirtualListHandle } from './virtualList.types';\n\n// Pure helpers live in ./virtualList.utils; re-exported here so existing\n// imports (and unit tests) keep working against the component entry point.\nexport {\n buildOffsets,\n findStartIndex,\n getVisibleRange,\n resolveReorderTarget,\n resolveTreeDropTarget,\n lastDescendantIndex,\n buildColumnTemplate,\n} from './virtualList.utils';\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n// VirtualListInner wires four focused hooks together and renders. Each concern\n// lives in its own module:\n// useVirtualWindow — generic scroll / measurement / windowing (all modes)\n// useSelection — multi-row selection\n// useColumns — table mode: columns, visibility, persistence, fit widths\n// useRowDrag — reorder + tree drag-and-drop (mouse + touch)\n\nfunction VirtualListInner<T>({\n items,\n renderRow,\n ariaRoles,\n columns,\n height = '100%',\n estimatedRowHeight = 40,\n overscan = 3,\n rowGap = 0,\n rowPadding,\n selectedKey,\n getItemKey,\n onRowClick,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n onLoadMore,\n loadMoreThreshold = 100,\n isLoading = false,\n multiSelect = false,\n selectedKeys,\n onSelectionChange,\n reorderable = false,\n onReorder,\n longPressDelay = 400,\n treeReorder = false,\n getItemDepth,\n isGroup,\n onTreeDrop,\n treeIndentPx = 24,\n dragHandle = false,\n showDivider = true,\n rowHover = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: VirtualListProps<T>, ref: React.ForwardedRef<VirtualListHandle>) {\n const getKey = useCallback(\n (item: T, index: number): string | number => (getItemKey ? getItemKey(item, index) : index),\n [getItemKey],\n );\n const keys = useMemo(() => items.map((item, i) => getKey(item, i)), [items, getKey]);\n const depths = useMemo(\n () => (getItemDepth ? items.map((item, i) => getItemDepth(item, i)) : []),\n [items, getItemDepth],\n );\n const isGroupAt = useCallback(\n (i: number) => (isGroup ? isGroup(items[i], i) : false),\n [isGroup, items],\n );\n\n const win = useVirtualWindow<T>({\n items, keys, getItemKey, estimatedRowHeight, rowGap, overscan,\n onLoadMore, loadMoreThreshold, isLoading,\n });\n const { rootRef, headerRef, rowObserver, keysRef, offsets, totalHeight, startIndex, endIndex } = win;\n\n const selection = useSelection<T>({ items, getKey, multiSelect, selectedKeys, onSelectionChange });\n const { effectiveSelectedKeys } = selection;\n\n const cols = useColumns<T>({\n columns, items, multiSelect, visibleColumnKeys, onVisibleColumnsChange, persistColumnsKey,\n showColumnToggle, rootRef, startIndex, endIndex,\n containerHeight: win.containerHeight, containerWidth: win.containerWidth,\n });\n const {\n hasColumns, visibleColumns, columnTemplate, shouldShowToggle, effectiveVisible, manuallyHiddenCount,\n toggleOpen, setToggleOpen, handleToggleColumn, recalculateColumns,\n } = cols;\n\n // Compose the forwarded handle from both hooks: scroll methods come from the\n // windowing engine, column controls from the column hook.\n useImperativeHandle(\n ref,\n () => ({ ...win.scrollApi, recalculateColumns }),\n [win.scrollApi, recalculateColumns],\n );\n\n const drag = useRowDrag({\n reorderable, treeReorder, onReorder, onTreeDrop, longPressDelay, dragHandle, treeIndentPx,\n keys, depths, isGroupAt, rootRef, keysRef,\n });\n\n const rowPaddingValue = typeof rowPadding === 'number' ? `${rowPadding}px` : rowPadding;\n\n const renderRowAt = (i: number) => {\n const item = items[i];\n const key = getKey(item, i);\n const isSelected = (selectedKey != null && key === selectedKey) || effectiveSelectedKeys.has(key);\n const dragProps = drag.getRowDragProps(i, key);\n\n return (\n <VirtualRow\n key={key}\n index={i}\n top={offsets[i]}\n padding={rowPaddingValue}\n columnTemplate={columnTemplate}\n isSelected={isSelected}\n showDivider={showDivider}\n hover={rowHover}\n onClick={() => {\n if (drag.consumeSuppressedClick()) return;\n onRowClick?.(item, i);\n }}\n observer={rowObserver}\n ariaRowIndex={hasColumns ? i + 2 : undefined}\n ariaPosInSet={hasColumns ? undefined : i + 1}\n ariaSetSize={hasColumns ? undefined : items.length}\n rowRole={ariaRoles?.row ?? (hasColumns ? 'row' : 'listitem')}\n reserveToggleGutter={shouldShowToggle}\n {...dragProps}\n dropIndicatorClassName={classNames?.dropIndicator}\n dropIndicatorStyle={slotStyles?.dropIndicator}\n rowClassName={classNames?.row}\n rowStyle={slotStyles?.row}\n >\n {hasColumns\n ? <>\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"gridcell\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n selected={effectiveSelectedKeys.has(key)}\n onToggle={() => selection.handleRowSelect(key)}\n aria-label=\"Select row\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListCell, classNames?.cell)}\n style={slotStyles?.cell}\n role=\"gridcell\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.renderCell(item, i)}\n </div>\n ))}\n </>\n : renderRow?.(item, i)}\n </VirtualRow>\n );\n };\n\n const visibleRows: React.ReactNode[] = [];\n for (let i = startIndex; i <= endIndex; i++) visibleRows.push(renderRowAt(i));\n\n // Keep the row being touch-dragged mounted even if it scrolls out of the\n // window. Touch events are dispatched to the element under the finger at\n // touchstart; if that row unmounts, the browser stops delivering touchmove\n // and the drag freezes. Pinning its DOM node keeps the gesture alive.\n const draggedIndex = drag.draggingKey != null ? keys.indexOf(drag.draggingKey) : -1;\n if (draggedIndex >= 0 && (draggedIndex < startIndex || draggedIndex > endIndex)) {\n visibleRows.push(renderRowAt(draggedIndex));\n }\n\n return (\n <div\n {...rest}\n ref={rootRef}\n className={cx(styles.virtualList, drag.draggingKey != null && styles.virtualListReordering, className, classNames?.root)}\n style={{ height, ...style, ...slotStyles?.root }}\n onScroll={win.handleScroll}\n role={ariaRoles?.container ?? (hasColumns ? 'grid' : 'list')}\n aria-rowcount={hasColumns ? items.length + 1 : undefined}\n >\n {hasColumns && (\n <div\n ref={headerRef}\n className={cx(styles.virtualListHeader, classNames?.header)}\n style={{ gridTemplateColumns: columnTemplate, ...(shouldShowToggle ? { paddingRight: 32 } : {}), ...slotStyles?.header }}\n role=\"row\"\n aria-rowindex={1}\n >\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"columnheader\"\n >\n <Checkbox\n selected={selection.allSelected || selection.someSelected}\n onToggle={selection.handleSelectAll}\n aria-label=\"Select all rows\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListHeaderCell, classNames?.headerCell)}\n style={slotStyles?.headerCell}\n role=\"columnheader\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.label}\n </div>\n ))}\n {shouldShowToggle && (\n <div className={styles.virtualListToggleWrapper}>\n <FloatingMenu\n isOpen={toggleOpen}\n onOpenChange={setToggleOpen}\n align={Align.Right}\n dontCloseOnChildClick\n content={\n <div\n className={cx(styles.virtualListTogglePopover, classNames?.togglePopover)}\n style={slotStyles?.togglePopover}\n >\n {columns!.filter((col) => !col.hideFromToggle).map((col) => (\n <Checkbox\n key={col.key}\n className={cx(styles.virtualListToggleItem, classNames?.toggleItem)}\n style={slotStyles?.toggleItem}\n selected={effectiveVisible.has(col.key)}\n onToggle={() => handleToggleColumn(col.key)}\n disabled={col.lockVisible}\n cursorDefault={false}\n >\n {col.toggleLabel ?? col.label}\n </Checkbox>\n ))}\n </div>\n }\n >\n <button\n type=\"button\"\n className={cx(styles.virtualListHeaderToggle, classNames?.headerToggle)}\n style={slotStyles?.headerToggle}\n aria-label=\"Toggle column visibility\"\n >\n <FontAwesomeIcon\n icon={faGear}\n style={slotStyles?.headerToggle as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </button>\n </FloatingMenu>\n {manuallyHiddenCount > 0 && (\n <span\n className={cx(styles.virtualListColumnChip, classNames?.columnChip)}\n style={slotStyles?.columnChip}\n data-column-hidden-count={manuallyHiddenCount}\n aria-label={`${manuallyHiddenCount} columns hidden`}\n >\n {manuallyHiddenCount}\n </span>\n )}\n </div>\n )}\n </div>\n )}\n {isLoading ? (\n <div className={styles.virtualListLoadingFull}>\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n ) : (\n <div\n className={cx(styles.virtualListBody, classNames?.body)}\n style={{ height: totalHeight, ...slotStyles?.body }}\n >\n {visibleRows}\n </div>\n )}\n {win.showLoadMoreSpinner && (\n <div\n className={cx(styles.virtualListLoadingIndicator, classNames?.loadingIndicator)}\n style={slotStyles?.loadingIndicator}\n >\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n )}\n </div>\n );\n}\n\n// forwardRef erases the generic, so cast back to a generic-preserving signature.\nconst VirtualList = React.forwardRef(VirtualListInner) as <T>(\n props: VirtualListProps<T> & { ref?: React.Ref<VirtualListHandle> },\n) => React.ReactElement | null;\n\nexport default VirtualList;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualRow.mjs","names":[],"sources":["../../../../package/common/virtualList/virtualRow.tsx"],"sourcesContent":["import React, { useRef, useLayoutEffect } from 'react';\nimport cx from 'classnames';\n\nimport styles from './virtualList.module.pcss';\nimport type { TreeDropPosition } from './virtualList.types';\n\nexport interface VirtualRowProps {\n index: number;\n top: number;\n /** Padding applied to the row (already normalised to a CSS string). */\n padding?: string;\n columnTemplate: string | undefined;\n isSelected: boolean;\n showDivider: boolean;\n hover: boolean;\n onClick: () => void;\n observer: ResizeObserver | null;\n ariaRowIndex?: number;\n ariaPosInSet?: number;\n ariaSetSize?: number;\n rowRole:
|
|
1
|
+
{"version":3,"file":"virtualRow.mjs","names":[],"sources":["../../../../package/common/virtualList/virtualRow.tsx"],"sourcesContent":["import React, { useRef, useLayoutEffect } from 'react';\nimport cx from 'classnames';\n\nimport styles from './virtualList.module.pcss';\nimport type { TreeDropPosition } from './virtualList.types';\n\nexport interface VirtualRowProps {\n index: number;\n top: number;\n /** Padding applied to the row (already normalised to a CSS string). */\n padding?: string;\n columnTemplate: string | undefined;\n isSelected: boolean;\n showDivider: boolean;\n hover: boolean;\n onClick: () => void;\n observer: ResizeObserver | null;\n ariaRowIndex?: number;\n ariaPosInSet?: number;\n ariaSetSize?: number;\n rowRole: string;\n reorderable?: boolean;\n /**\n * Native mouse DnD is active for the list. Distinct from `draggable`, which in\n * `dragHandle` mode is only set on the row the pointer has armed.\n */\n mouseDragEnabled?: boolean;\n draggable?: boolean;\n isDragging?: boolean;\n reserveToggleGutter?: boolean;\n onMouseDown?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onMouseOver?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onMouseLeave?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onDragStart?: (e: React.DragEvent<HTMLDivElement>) => void;\n onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;\n onDragEnd?: () => void;\n onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;\n onTouchStart?: (e: React.TouchEvent<HTMLDivElement>) => void;\n dropPosition?: TreeDropPosition;\n dropIndentPx?: number;\n dropIndicatorClassName?: string;\n dropIndicatorStyle?: React.CSSProperties;\n rowClassName?: string;\n rowStyle?: React.CSSProperties;\n children: React.ReactNode;\n}\n\n/**\n * A single virtualized row: absolutely positioned at its `top`, optionally a\n * grid (table mode), registering itself with the shared ResizeObserver and\n * carrying all the drag / drop-indicator wiring the parent assigns it.\n */\nfunction VirtualRow({\n index,\n top,\n padding,\n columnTemplate,\n isSelected,\n showDivider,\n hover,\n onClick,\n observer,\n ariaRowIndex,\n ariaPosInSet,\n ariaSetSize,\n rowRole,\n reorderable,\n mouseDragEnabled,\n draggable,\n isDragging,\n reserveToggleGutter,\n onMouseDown,\n onMouseOver,\n onMouseLeave,\n onDragStart,\n onDragOver,\n onDragEnd,\n onDrop,\n onTouchStart,\n dropPosition,\n dropIndentPx,\n dropIndicatorClassName,\n dropIndicatorStyle,\n rowClassName,\n rowStyle,\n children,\n}: VirtualRowProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n // A single observer is shared across all rows (created by the parent); each\n // row just registers/unregisters its element. The parent reads the row index\n // back from the `data-index` attribute when the observer fires.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || !observer) return;\n observer.observe(el);\n return () => observer.unobserve(el);\n }, [observer]);\n\n return (\n <div\n ref={ref}\n data-index={index}\n className={cx(\n styles.virtualListRow,\n isSelected && styles.virtualListRowSelected,\n !showDivider && styles.virtualListRowNoDivider,\n !hover && styles.virtualListRowNoHover,\n reorderable && styles.virtualListRowDraggable,\n isDragging && styles.virtualListRowDragging,\n dropPosition === 'inside' && styles.virtualListRowDropInside,\n rowClassName,\n )}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n transform: `translateY(${top}px)`,\n ...(padding != null ? { padding } : {}),\n ...(columnTemplate ? { display: 'grid', gridTemplateColumns: columnTemplate } : {}),\n // Match the header's reserved gutter for the column-toggle cog so row\n // cells line up with their header cells instead of drifting under it.\n // Applied after `padding` so the alignment gutter always wins on the right.\n ...(reserveToggleGutter ? { paddingRight: 32 } : {}),\n ...rowStyle,\n }}\n onClick={onClick}\n draggable={draggable}\n onMouseDown={onMouseDown}\n onMouseOver={onMouseOver}\n onMouseLeave={onMouseLeave}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDrop={onDrop ?? (mouseDragEnabled ? (e) => e.preventDefault() : undefined)}\n onTouchStart={onTouchStart}\n onContextMenu={mouseDragEnabled ? (e) => e.preventDefault() : undefined}\n aria-selected={isSelected}\n aria-rowindex={ariaRowIndex}\n aria-posinset={ariaPosInSet}\n aria-setsize={ariaSetSize}\n role={rowRole}\n >\n {(dropPosition === 'before' || dropPosition === 'after') && (\n <div\n data-drop-line={dropPosition}\n aria-hidden\n className={cx(\n styles.virtualListDropLine,\n dropPosition === 'before' ? styles.virtualListDropLineBefore : styles.virtualListDropLineAfter,\n dropIndicatorClassName,\n )}\n style={{ left: dropIndentPx ?? 0, ...dropIndicatorStyle }}\n />\n )}\n {children}\n </div>\n );\n}\n\nexport default VirtualRow;\n"],"mappings":"wKAoDA,SAAS,EAAW,CAClB,QACA,MACA,UACA,iBACA,aACA,cACA,QACA,UACA,WACA,eACA,eACA,cACA,UACA,cACA,mBACA,YACA,aACA,sBACA,cACA,cACA,eACA,cACA,aACA,YACA,SACA,eACA,eACA,eACA,yBACA,qBACA,eACA,WACA,YACkB,CAClB,IAAM,EAAM,EAAuB,IAAI,EAYvC,OAPA,MAAsB,CACpB,IAAM,EAAK,EAAI,QACX,MAAC,GAAM,CAAC,GAEZ,OADA,EAAS,QAAQ,CAAE,MACN,EAAS,UAAU,CAAE,CACpC,EAAG,CAAC,CAAQ,CAAC,EAGX,EAAC,MAAD,CACO,MACL,aAAY,EACZ,UAAW,EACT,EAAO,eACP,GAAc,EAAO,uBACrB,CAAC,GAAe,EAAO,wBACvB,CAAC,GAAS,EAAO,sBACjB,GAAe,EAAO,wBACtB,GAAc,EAAO,uBACrB,IAAiB,UAAY,EAAO,yBACpC,CACF,EACA,MAAO,CACL,SAAU,WACV,IAAK,EACL,KAAM,EACN,MAAO,EACP,UAAW,cAAc,EAAI,KAC7B,GAAI,GAAW,KAAqB,CAAC,EAAf,CAAE,SAAQ,EAChC,GAAI,EAAiB,CAAE,QAAS,OAAQ,oBAAqB,CAAe,EAAI,CAAC,EAIjF,GAAI,EAAsB,CAAE,aAAc,EAAG,EAAI,CAAC,EAClD,GAAG,CACL,EACS,UACE,YACE,cACA,cACC,eACD,cACD,aACD,YACX,OAAQ,IAAW,EAAoB,GAAM,EAAE,eAAe,EAAI,IAAA,IACpD,eACd,cAAe,EAAoB,GAAM,EAAE,eAAe,EAAI,IAAA,GAC9D,gBAAe,EACf,gBAAe,EACf,gBAAe,EACf,eAAc,EACd,KAAM,WA1CR,EA4CI,IAAiB,UAAY,IAAiB,UAC9C,EAAC,MAAD,CACE,iBAAgB,EAChB,cAAA,GACA,UAAW,EACT,EAAO,oBACP,IAAiB,SAAW,EAAO,0BAA4B,EAAO,yBACtE,CACF,EACA,MAAO,CAAE,KAAM,GAAgB,EAAG,GAAG,CAAmB,CACzD,CAAA,EAEF,CACE,GAET"}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AccordionStyleType as e}from"./common/accordion/accordion.types.mjs";import t from"./common/configProvider/configProvider.mjs";import{useComponentDefaults as n}from"./common/configProvider/useComponentDefaults.mjs";import{usePresentationDefault as r}from"./common/configProvider/usePresentationDefault.mjs";import i from"./common/accordion/accordion.mjs";import a from"./common/loading/spinnerLoading/index.mjs";import{ButtonSize as o,ButtonStyleType as s,ButtonType as c}from"./common/button/button.types.mjs";import l from"./common/ripple/ripple.mjs";import u from"./common/button/button.mjs";import d from"./common/actionButtons/actionButtons.mjs";import f from"./common/interactableDiv/index.mjs";import p from"./common/actionIcon/actionIcon.mjs";import{AlertStyleType as m}from"./common/alert/alert.types.mjs";import h from"./common/alert/alert.mjs";import g from"./common/animatedLogo/animatedLogo.mjs";import{AnimatedTextUnit as _,AnimatedTextVariant as v}from"./common/animatedText/animatedText.types.mjs";import y from"./common/animatedText/animatedText.mjs";import{BadgePosition as b,BadgeStyleType as x}from"./common/badge/badge.types.mjs";import S from"./common/badge/badge.mjs";import C from"./common/avatar/avatar.mjs";import w from"./common/avatar/avatarGroup.mjs";import T from"./common/bodyEnd/bodyEnd.mjs";import{Align as E,Presentation as D}from"./common/floatingMenu/floatingMenu.types.mjs";import O from"./common/floatingMenu/floatingMenu.mjs";import k from"./common/breadcrumb/breadcrumb.mjs";import{ButtonGroupOrientation as A}from"./common/buttonGroup/buttonGroup.types.mjs";import j from"./common/buttonGroup/buttonGroup.mjs";import{CardStyleType as M}from"./common/card/card.types.mjs";import N from"./common/card/Card.mjs";import P from"./common/card/CardHeader.mjs";import F from"./common/card/CardMedia.mjs";import I from"./common/card/CardContent.mjs";import L from"./common/card/CardActions.mjs";import R from"./common/carousel/carousel.mjs";import z from"./common/checkbox/checkbox.mjs";import{ChipStyleType as B}from"./common/chip/chip.types.mjs";import V from"./common/chip/chip.mjs";import H from"./common/chip/chipContainer.mjs";import U from"./common/tooltip/tooltip.mjs";import{InputIconPosition as W,InputType as G}from"./common/input/input.types.mjs";import K from"./common/input/input.mjs";import q from"./common/colorPicker/colorPicker.mjs";import J from"./common/modal/modal.mjs";import Y from"./common/confirmModal/confirmModal.mjs";import{getLocale as X,mapLocale as Z,setLocale as Q}from"./services/localization.mjs";import $ from"./common/infiniteBlock/infiniteBlock.mjs";import ee from"./common/dropdown/dropdown.mjs";import te from"./common/datePicker/datePicker.mjs";import{DividerOrientation as ne,DividerTextPosition as re}from"./common/divider/divider.types.mjs";import ie from"./common/divider/divider.mjs";import ae from"./common/drawer/drawer.mjs";import{DropZoneReturnType as oe,DropZoneStatus as se}from"./common/dropZone/dropZone.types.mjs";import ce from"./common/dropZone/dropZone.mjs";import le from"./common/emptyState/emptyState.mjs";import{showToast as ue}from"./common/toast/toastService.mjs";import de from"./common/toast/toastProvider.mjs";import fe from"./common/errorBoundary/errorBoundary.mjs";import pe from"./common/fab/fab.mjs";import me from"./common/flip/flip.mjs";import{DoorSwing as he,OpeningKind as ge,PlanIssueKind as _e,PlanUnitSystem as ve,WallType as ye}from"./common/floorPlan/floorPlan.types.mjs";import{MIN_OPENING_WIDTH as be,MIN_WALL_LENGTH as xe}from"./common/floorPlan/floorPlan.geometry.mjs";import{DEFAULT_WALL_ATTRS as Se,addOpening as Ce,addRect as we,addWall as Te,cleanupPlan as Ee,detachWall as De,dissolveNode as Oe,mergeNodes as ke,moveNode as Ae,removeOpening as je,removeWall as Me,scalePlan as Ne,splitWall as Pe,transformPlan as Fe,updateOpening as Ie,validatePlan as Le,wallLength as Re,weldShortWalls as ze}from"./common/floorPlan/floorPlan.graph.mjs";import{MIN_FLOOR_HEIGHT as Be,addFloor as Ve,duplicateFloor as He,emptyFloor as Ue,emptyFloorPlan as We,floorBelow as Ge,floorBounds as Ke,floorIndex as qe,getFloor as Je,moveFloor as Ye,removeFloor as Xe,renameFloor as Ze,setFloor as Qe,setFloorHeight as $e,updateFloor as et}from"./common/floorPlan/floorPlan.plan.mjs";import{deriveFaces as tt,nodeDegrees as nt}from"./common/floorPlan/floorPlan.faces.mjs";import{commitDerivation as rt,derivePlan as it,pruneUnmatchedRooms as at,roomAtPoint as ot}from"./common/floorPlan/floorPlan.rooms.mjs";import{buildWallPaths as st,openingGeometry as ct,wallCentrelineSpans as lt}from"./common/floorPlan/floorPlan.path.mjs";import{HIT_PX as ut,HIT_PX_COARSE as dt,hitTest as ft,selectionsEqual as pt,worldTolerances as mt}from"./common/floorPlan/floorPlan.hit.mjs";import{DEFAULT_SNAP_OPTIONS as ht,SnapKind as gt,clientToWorld as _t,resolveSnap as vt,screenScale as yt}from"./common/floorPlan/floorPlan.snap.mjs";import{PLAN_FORMAT_VERSION as bt,planFromJson as xt,planToJson as St}from"./common/floorPlan/floorPlan.json.mjs";import{buildPlanMesh as Ct}from"./common/floorPlan/floorPlan.mesh.mjs";import{planFromLegacySvg as wt}from"./common/floorPlan/legacySvg.mjs";import Tt from"./common/iconPicker/iconPicker.mjs";import Et from"./common/idleManager/idleManager.mjs";import Dt from"./common/inputDropdown/inputDropdown.mjs";import Ot from"./common/kanbanBoard/KanbanColumn.mjs";import kt from"./common/kanbanBoard/KanbanBoard.mjs";import At from"./common/searchInput/searchInput.mjs";import jt from"./common/klipyPicker/klipyPicker.mjs";import Mt from"./common/loading/iconLoading/index.mjs";import Nt from"./common/numberInput/index.mjs";import Pt from"./common/optionPicker/optionPicker.mjs";import{OtpInputCharset as Ft}from"./common/otpInput/otpInput.types.mjs";import It from"./common/otpInput/otpInput.mjs";import Lt from"./common/overscroll/overscroll.mjs";import{PopoverAlign as Rt,PopoverPlacement as zt,PopoverTrigger as Bt}from"./common/popover/popover.types.mjs";import Vt from"./common/popover/popover.mjs";import Ht from"./common/progressBar/progressBar.mjs";import{RadioGroupOrientation as Ut}from"./common/radioGroup/radioGroup.types.mjs";import Wt from"./common/radioGroup/radioGroup.mjs";import Gt from"./common/rating/rating.mjs";import Kt from"./common/revealLens/revealLens.mjs";import qt from"./common/roomDrawer/roomDrawer.mjs";import Jt from"./common/roomViewer/roomViewer.mjs";import Yt from"./common/scrollbarProvider/index.mjs";import{SectionHeaderSize as Xt}from"./common/sectionHeader/sectionHeader.types.mjs";import Zt from"./common/sectionHeader/sectionHeader.mjs";import{SkeletonAnimation as Qt,SkeletonVariant as $t}from"./common/skeleton/skeleton.types.mjs";import en from"./common/skeleton/skeleton.mjs";import tn from"./common/slider/slider.mjs";import nn from"./common/splitButton/splitButton.mjs";import{StepperAlignment as rn,StepperCollapse as an,StepperLabelPlacement as on,StepperStyleType as sn}from"./common/stepper/stepper.types.mjs";import cn from"./common/stepper/stepper.mjs";import ln from"./common/sticky/sticky.mjs";import un from"./common/switch/switch.mjs";import dn from"./common/tabHeader/tabHeader.mjs";import fn from"./common/textarea/textarea.mjs";import{defaultTheme as pn}from"./common/themeProvider/defaultTheme.mjs";import mn from"./common/themeProvider/themeProvider.mjs";import{useTheme as hn}from"./common/themeProvider/useTheme.mjs";import gn,{TiltGroupContext as _n,useTiltGroup as vn}from"./common/tiltGroup/tiltGroup.mjs";import{defaultTiltEasing as yn}from"./common/tilt/tiltMath.mjs";import bn from"./common/tilt/tilt.mjs";import xn from"./common/timeInput/timeInput.mjs";import{TimelineAlignment as Sn,TimelineItemStatus as Cn}from"./common/timeline/timeline.types.mjs";import wn from"./common/timeline/timeline.mjs";import Tn from"./common/timer/timer.mjs";import En from"./common/virtualList/virtualList.mjs";import Dn from"./common/wizard/wizard.mjs";import On from"./services/formValidation/FormValidatorGroupWithForm.mjs";import kn from"./services/formValidation/validatableComponent.mjs";import{useFormValidatorGroup as An}from"./services/formValidation/useFormValidatorGroup.mjs";import{FormValidator as jn,Validators as Mn,useFormValidator as Nn}from"./services/formValidation/index.mjs";import{hasEightPasswordChars as Pn,hasOnePasswordDigit as Fn,hasOnePasswordLetter as In,isBic as Ln,isDate as Rn,isEmail as zn,isISODate as Bn,isNumber as Vn,isPassword as Hn,isURL as Un}from"@ahrowe/form-validation";export{i as Accordion,e as AccordionStyleType,d as ActionButtons,p as ActionIcon,h as Alert,m as AlertStyleType,E as Align,g as AnimatedLogo,y as AnimatedText,_ as AnimatedTextUnit,v as AnimatedTextVariant,C as Avatar,w as AvatarGroup,S as Badge,b as BadgePosition,x as BadgeStyleType,T as BodyEnd,k as Breadcrumb,u as Button,j as ButtonGroup,A as ButtonGroupOrientation,o as ButtonSize,s as ButtonStyleType,c as ButtonType,N as Card,L as CardActions,I as CardContent,P as CardHeader,F as CardMedia,M as CardStyleType,R as Carousel,z as Checkbox,V as Chip,H as ChipContainer,B as ChipStyleType,q as ColorPicker,t as ConfigProvider,Y as ConfirmModal,ht as DEFAULT_SNAP_OPTIONS,Se as DEFAULT_WALL_ATTRS,te as DatePicker,ie as Divider,ne as DividerOrientation,re as DividerTextPosition,he as DoorSwing,ae as Drawer,ce as DropZone,oe as DropZoneReturnType,se as DropZoneStatus,ee as Dropdown,le as EmptyState,fe as ErrorBoundary,pe as Fab,me as Flip,O as FloatingMenu,jn as FormValidator,On as FormValidatorGroup,ut as HIT_PX,dt as HIT_PX_COARSE,Mt as IconLoading,Tt as IconPicker,Et as IdleManager,$ as InfiniteBlock,K as Input,Dt as InputDropdown,W as InputIconPosition,G as InputType,f as InteractableDiv,kt as KanbanBoard,Ot as KanbanColumn,jt as KlipyPicker,Be as MIN_FLOOR_HEIGHT,be as MIN_OPENING_WIDTH,xe as MIN_WALL_LENGTH,J as Modal,Nt as NumberInput,ge as OpeningKind,Pt as OptionPicker,It as OtpInput,Ft as OtpInputCharset,Lt as Overscroll,bt as PLAN_FORMAT_VERSION,_e as PlanIssueKind,ve as PlanUnitSystem,Vt as Popover,Rt as PopoverAlign,zt as PopoverPlacement,Bt as PopoverTrigger,D as Presentation,Ht as ProgressBar,Wt as RadioGroup,Ut as RadioGroupOrientation,Gt as Rating,Kt as RevealLens,l as Ripple,qt as RoomDrawer,Jt as RoomViewer,Yt as ScrollbarProvider,At as SearchInput,Zt as SectionHeader,Xt as SectionHeaderSize,en as Skeleton,Qt as SkeletonAnimation,$t as SkeletonVariant,tn as Slider,gt as SnapKind,a as SpinnerLoading,nn as SplitButton,cn as Stepper,rn as StepperAlignment,an as StepperCollapse,on as StepperLabelPlacement,sn as StepperStyleType,ln as Sticky,un as Switch,dn as TabHeader,fn as Textarea,mn as ThemeProvider,bn as Tilt,gn as TiltGroup,_n as TiltGroupContext,xn as TimeInput,wn as Timeline,Sn as TimelineAlignment,Cn as TimelineItemStatus,Tn as Timer,de as ToastProvider,U as Tooltip,kn as ValidatableComponent,Mn as Validators,En as VirtualList,ye as WallType,Dn as Wizard,Ve as addFloor,Ce as addOpening,we as addRect,Te as addWall,Ct as buildPlanMesh,st as buildWallPaths,Ee as cleanupPlan,_t as clientToWorld,rt as commitDerivation,pn as defaultTheme,yn as defaultTiltEasing,tt as deriveFaces,it as derivePlan,De as detachWall,Oe as dissolveNode,He as duplicateFloor,Ue as emptyFloor,We as emptyFloorPlan,Ge as floorBelow,Ke as floorBounds,qe as floorIndex,Je as getFloor,X as getLocale,Pn as hasEightPasswordChars,Fn as hasOnePasswordDigit,In as hasOnePasswordLetter,ft as hitTest,Ln as isBic,Rn as isDate,zn as isEmail,Bn as isISODate,Vn as isNumber,Hn as isPassword,Un as isURL,Z as mapLocale,ke as mergeNodes,Ye as moveFloor,Ae as moveNode,nt as nodeDegrees,ct as openingGeometry,xt as planFromJson,wt as planFromLegacySvg,St as planToJson,at as pruneUnmatchedRooms,Xe as removeFloor,je as removeOpening,Me as removeWall,Ze as renameFloor,vt as resolveSnap,ot as roomAtPoint,Ne as scalePlan,yt as screenScale,pt as selectionsEqual,Qe as setFloor,$e as setFloorHeight,Q as setLocale,ue as showToast,Pe as splitWall,Fe as transformPlan,et as updateFloor,Ie as updateOpening,n as useComponentDefaults,Nn as useFormValidator,An as useFormValidatorGroup,r as usePresentationDefault,hn as useTheme,vn as useTiltGroup,Le as validatePlan,lt as wallCentrelineSpans,Re as wallLength,ze as weldShortWalls,mt as worldTolerances};
|
|
1
|
+
import{AccordionStyleType as e}from"./common/accordion/accordion.types.mjs";import t from"./common/configProvider/configProvider.mjs";import{useComponentDefaults as n}from"./common/configProvider/useComponentDefaults.mjs";import{usePresentationDefault as r}from"./common/configProvider/usePresentationDefault.mjs";import i from"./common/accordion/accordion.mjs";import a from"./common/loading/spinnerLoading/index.mjs";import{ButtonSize as o,ButtonStyleType as s,ButtonType as c}from"./common/button/button.types.mjs";import l from"./common/ripple/ripple.mjs";import u from"./common/button/button.mjs";import d from"./common/actionButtons/actionButtons.mjs";import f from"./common/interactableDiv/index.mjs";import p from"./common/actionIcon/actionIcon.mjs";import{AlertStyleType as m}from"./common/alert/alert.types.mjs";import h from"./common/alert/alert.mjs";import g from"./common/animatedLogo/animatedLogo.mjs";import{AnimatedTextUnit as _,AnimatedTextVariant as v}from"./common/animatedText/animatedText.types.mjs";import y from"./common/animatedText/animatedText.mjs";import{BadgePosition as b,BadgeStyleType as x}from"./common/badge/badge.types.mjs";import S from"./common/badge/badge.mjs";import C from"./common/avatar/avatar.mjs";import w from"./common/avatar/avatarGroup.mjs";import T from"./common/bodyEnd/bodyEnd.mjs";import{Align as E,Presentation as D}from"./common/floatingMenu/floatingMenu.types.mjs";import O from"./common/floatingMenu/floatingMenu.mjs";import k from"./common/breadcrumb/breadcrumb.mjs";import{ButtonGroupOrientation as A}from"./common/buttonGroup/buttonGroup.types.mjs";import j from"./common/buttonGroup/buttonGroup.mjs";import{CardStyleType as M}from"./common/card/card.types.mjs";import N from"./common/card/Card.mjs";import P from"./common/card/CardHeader.mjs";import F from"./common/card/CardMedia.mjs";import I from"./common/card/CardContent.mjs";import L from"./common/card/CardActions.mjs";import R from"./common/carousel/carousel.mjs";import z from"./common/checkbox/checkbox.mjs";import{ChipStyleType as B}from"./common/chip/chip.types.mjs";import V from"./common/chip/chip.mjs";import H from"./common/chip/chipContainer.mjs";import U from"./common/tooltip/tooltip.mjs";import{InputIconPosition as W,InputType as G}from"./common/input/input.types.mjs";import K from"./common/input/input.mjs";import q from"./common/colorPicker/colorPicker.mjs";import J from"./common/modal/modal.mjs";import Y from"./common/confirmModal/confirmModal.mjs";import{getLocale as X,mapLocale as Z,setLocale as Q}from"./services/localization.mjs";import $ from"./common/infiniteBlock/infiniteBlock.mjs";import ee from"./common/dropdown/dropdown.mjs";import te from"./common/datePicker/datePicker.mjs";import{DividerOrientation as ne,DividerTextPosition as re}from"./common/divider/divider.types.mjs";import ie from"./common/divider/divider.mjs";import ae from"./common/drawer/drawer.mjs";import{DropZoneReturnType as oe,DropZoneStatus as se}from"./common/dropZone/dropZone.types.mjs";import ce from"./common/dropZone/dropZone.mjs";import le from"./common/emptyState/emptyState.mjs";import{showToast as ue}from"./common/toast/toastService.mjs";import de from"./common/toast/toastProvider.mjs";import fe from"./common/errorBoundary/errorBoundary.mjs";import pe from"./common/fab/fab.mjs";import me from"./common/flip/flip.mjs";import{DoorSwing as he,OpeningKind as ge,PlanIssueKind as _e,PlanUnitSystem as ve,WallType as ye}from"./common/floorPlan/floorPlan.types.mjs";import{MIN_OPENING_WIDTH as be,MIN_WALL_LENGTH as xe}from"./common/floorPlan/floorPlan.geometry.mjs";import{DEFAULT_WALL_ATTRS as Se,addOpening as Ce,addRect as we,addWall as Te,cleanupPlan as Ee,detachWall as De,dissolveNode as Oe,mergeNodes as ke,moveNode as Ae,removeOpening as je,removeWall as Me,scalePlan as Ne,splitWall as Pe,transformPlan as Fe,updateOpening as Ie,validatePlan as Le,wallLength as Re,weldShortWalls as ze}from"./common/floorPlan/floorPlan.graph.mjs";import{MIN_FLOOR_HEIGHT as Be,addFloor as Ve,duplicateFloor as He,emptyFloor as Ue,emptyFloorPlan as We,floorBelow as Ge,floorBounds as Ke,floorIndex as qe,getFloor as Je,moveFloor as Ye,removeFloor as Xe,renameFloor as Ze,setFloor as Qe,setFloorHeight as $e,updateFloor as et}from"./common/floorPlan/floorPlan.plan.mjs";import{deriveFaces as tt,nodeDegrees as nt}from"./common/floorPlan/floorPlan.faces.mjs";import{commitDerivation as rt,derivePlan as it,pruneUnmatchedRooms as at,roomAtPoint as ot}from"./common/floorPlan/floorPlan.rooms.mjs";import{buildWallPaths as st,openingGeometry as ct,wallCentrelineSpans as lt}from"./common/floorPlan/floorPlan.path.mjs";import{HIT_PX as ut,HIT_PX_COARSE as dt,hitTest as ft,selectionsEqual as pt,worldTolerances as mt}from"./common/floorPlan/floorPlan.hit.mjs";import{DEFAULT_SNAP_OPTIONS as ht,SnapKind as gt,clientToWorld as _t,resolveSnap as vt,screenScale as yt}from"./common/floorPlan/floorPlan.snap.mjs";import{PLAN_FORMAT_VERSION as bt,planFromJson as xt,planToJson as St}from"./common/floorPlan/floorPlan.json.mjs";import{buildPlanMesh as Ct}from"./common/floorPlan/floorPlan.mesh.mjs";import{planFromLegacySvg as wt}from"./common/floorPlan/legacySvg.mjs";import Tt from"./common/iconPicker/iconPicker.mjs";import Et from"./common/idleManager/idleManager.mjs";import Dt from"./common/inputDropdown/inputDropdown.mjs";import Ot from"./common/kanbanBoard/KanbanColumn.mjs";import kt from"./common/kanbanBoard/KanbanBoard.mjs";import At from"./common/searchInput/searchInput.mjs";import jt from"./common/klipyPicker/klipyPicker.mjs";import Mt from"./common/loading/iconLoading/index.mjs";import{PopoverAlign as Nt,PopoverPlacement as Pt,PopoverTrigger as Ft}from"./common/popover/popover.types.mjs";import It from"./common/popover/popover.mjs";import Lt from"./common/multiSelect/multiSelect.mjs";import Rt from"./common/numberInput/index.mjs";import zt from"./common/optionPicker/optionPicker.mjs";import{OtpInputCharset as Bt}from"./common/otpInput/otpInput.types.mjs";import Vt from"./common/otpInput/otpInput.mjs";import Ht from"./common/overscroll/overscroll.mjs";import Ut from"./common/pagination/pagination.mjs";import Wt from"./common/progressBar/progressBar.mjs";import{RadioGroupOrientation as Gt}from"./common/radioGroup/radioGroup.types.mjs";import Kt from"./common/radioGroup/radioGroup.mjs";import qt from"./common/rating/rating.mjs";import Jt from"./common/revealLens/revealLens.mjs";import Yt from"./common/roomDrawer/roomDrawer.mjs";import Xt from"./common/roomViewer/roomViewer.mjs";import Zt from"./common/scrollbarProvider/index.mjs";import{SectionHeaderSize as Qt}from"./common/sectionHeader/sectionHeader.types.mjs";import $t from"./common/sectionHeader/sectionHeader.mjs";import{SkeletonAnimation as en,SkeletonVariant as tn}from"./common/skeleton/skeleton.types.mjs";import nn from"./common/skeleton/skeleton.mjs";import rn from"./common/slider/slider.mjs";import an from"./common/splitButton/splitButton.mjs";import{StepperAlignment as on,StepperCollapse as sn,StepperLabelPlacement as cn,StepperStyleType as ln}from"./common/stepper/stepper.types.mjs";import un from"./common/stepper/stepper.mjs";import dn from"./common/sticky/sticky.mjs";import fn from"./common/switch/switch.mjs";import pn from"./common/tabHeader/tabHeader.mjs";import mn from"./common/textarea/textarea.mjs";import{defaultTheme as hn}from"./common/themeProvider/defaultTheme.mjs";import gn from"./common/themeProvider/themeProvider.mjs";import{useTheme as _n}from"./common/themeProvider/useTheme.mjs";import vn,{TiltGroupContext as yn,useTiltGroup as bn}from"./common/tiltGroup/tiltGroup.mjs";import{defaultTiltEasing as xn}from"./common/tilt/tiltMath.mjs";import Sn from"./common/tilt/tilt.mjs";import Cn from"./common/timeInput/timeInput.mjs";import{TimelineAlignment as wn,TimelineItemStatus as Tn}from"./common/timeline/timeline.types.mjs";import En from"./common/timeline/timeline.mjs";import Dn from"./common/timer/timer.mjs";import On from"./common/virtualList/virtualList.mjs";import{flattenTree as kn}from"./common/tree/flattenTree.mjs";import An from"./common/tree/tree.mjs";import jn from"./common/wizard/wizard.mjs";import Mn from"./services/formValidation/FormValidatorGroupWithForm.mjs";import Nn from"./services/formValidation/validatableComponent.mjs";import{useFormValidatorGroup as Pn}from"./services/formValidation/useFormValidatorGroup.mjs";import{FormValidator as Fn,Validators as In,useFormValidator as Ln}from"./services/formValidation/index.mjs";import{hasEightPasswordChars as Rn,hasOnePasswordDigit as zn,hasOnePasswordLetter as Bn,isBic as Vn,isDate as Hn,isEmail as Un,isISODate as Wn,isNumber as Gn,isPassword as Kn,isURL as qn}from"@ahrowe/form-validation";export{i as Accordion,e as AccordionStyleType,d as ActionButtons,p as ActionIcon,h as Alert,m as AlertStyleType,E as Align,g as AnimatedLogo,y as AnimatedText,_ as AnimatedTextUnit,v as AnimatedTextVariant,C as Avatar,w as AvatarGroup,S as Badge,b as BadgePosition,x as BadgeStyleType,T as BodyEnd,k as Breadcrumb,u as Button,j as ButtonGroup,A as ButtonGroupOrientation,o as ButtonSize,s as ButtonStyleType,c as ButtonType,N as Card,L as CardActions,I as CardContent,P as CardHeader,F as CardMedia,M as CardStyleType,R as Carousel,z as Checkbox,V as Chip,H as ChipContainer,B as ChipStyleType,q as ColorPicker,t as ConfigProvider,Y as ConfirmModal,ht as DEFAULT_SNAP_OPTIONS,Se as DEFAULT_WALL_ATTRS,te as DatePicker,ie as Divider,ne as DividerOrientation,re as DividerTextPosition,he as DoorSwing,ae as Drawer,ce as DropZone,oe as DropZoneReturnType,se as DropZoneStatus,ee as Dropdown,le as EmptyState,fe as ErrorBoundary,pe as Fab,me as Flip,O as FloatingMenu,Fn as FormValidator,Mn as FormValidatorGroup,ut as HIT_PX,dt as HIT_PX_COARSE,Mt as IconLoading,Tt as IconPicker,Et as IdleManager,$ as InfiniteBlock,K as Input,Dt as InputDropdown,W as InputIconPosition,G as InputType,f as InteractableDiv,kt as KanbanBoard,Ot as KanbanColumn,jt as KlipyPicker,Be as MIN_FLOOR_HEIGHT,be as MIN_OPENING_WIDTH,xe as MIN_WALL_LENGTH,J as Modal,Lt as MultiSelect,Rt as NumberInput,ge as OpeningKind,zt as OptionPicker,Vt as OtpInput,Bt as OtpInputCharset,Ht as Overscroll,bt as PLAN_FORMAT_VERSION,Ut as Pagination,_e as PlanIssueKind,ve as PlanUnitSystem,It as Popover,Nt as PopoverAlign,Pt as PopoverPlacement,Ft as PopoverTrigger,D as Presentation,Wt as ProgressBar,Kt as RadioGroup,Gt as RadioGroupOrientation,qt as Rating,Jt as RevealLens,l as Ripple,Yt as RoomDrawer,Xt as RoomViewer,Zt as ScrollbarProvider,At as SearchInput,$t as SectionHeader,Qt as SectionHeaderSize,nn as Skeleton,en as SkeletonAnimation,tn as SkeletonVariant,rn as Slider,gt as SnapKind,a as SpinnerLoading,an as SplitButton,un as Stepper,on as StepperAlignment,sn as StepperCollapse,cn as StepperLabelPlacement,ln as StepperStyleType,dn as Sticky,fn as Switch,pn as TabHeader,mn as Textarea,gn as ThemeProvider,Sn as Tilt,vn as TiltGroup,yn as TiltGroupContext,Cn as TimeInput,En as Timeline,wn as TimelineAlignment,Tn as TimelineItemStatus,Dn as Timer,de as ToastProvider,U as Tooltip,An as Tree,Nn as ValidatableComponent,In as Validators,On as VirtualList,ye as WallType,jn as Wizard,Ve as addFloor,Ce as addOpening,we as addRect,Te as addWall,Ct as buildPlanMesh,st as buildWallPaths,Ee as cleanupPlan,_t as clientToWorld,rt as commitDerivation,hn as defaultTheme,xn as defaultTiltEasing,tt as deriveFaces,it as derivePlan,De as detachWall,Oe as dissolveNode,He as duplicateFloor,Ue as emptyFloor,We as emptyFloorPlan,kn as flattenTree,Ge as floorBelow,Ke as floorBounds,qe as floorIndex,Je as getFloor,X as getLocale,Rn as hasEightPasswordChars,zn as hasOnePasswordDigit,Bn as hasOnePasswordLetter,ft as hitTest,Vn as isBic,Hn as isDate,Un as isEmail,Wn as isISODate,Gn as isNumber,Kn as isPassword,qn as isURL,Z as mapLocale,ke as mergeNodes,Ye as moveFloor,Ae as moveNode,nt as nodeDegrees,ct as openingGeometry,xt as planFromJson,wt as planFromLegacySvg,St as planToJson,at as pruneUnmatchedRooms,Xe as removeFloor,je as removeOpening,Me as removeWall,Ze as renameFloor,vt as resolveSnap,ot as roomAtPoint,Ne as scalePlan,yt as screenScale,pt as selectionsEqual,Qe as setFloor,$e as setFloorHeight,Q as setLocale,ue as showToast,Pe as splitWall,Fe as transformPlan,et as updateFloor,Ie as updateOpening,n as useComponentDefaults,Ln as useFormValidator,Pn as useFormValidatorGroup,r as usePresentationDefault,_n as useTheme,bn as useTiltGroup,Le as validatePlan,lt as wallCentrelineSpans,Re as wallLength,ze as weldShortWalls,mt as worldTolerances};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validatableComponent.mjs","names":[],"sources":["../../../../package/services/formValidation/validatableComponent.tsx"],"sourcesContent":["
|
|
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(() => { this.forceUpdate(); });\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(() => { this.forceUpdate(); });\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\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n }\n\n isRequired(): boolean {\n const { isRequired, formValidator } = this.props;\n return !!(isRequired\n || (formValidator && formValidator.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')));\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":"8HA0BA,IAAqB,EAArB,cAGU,CAAoB,0BAC8B,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,CAAE,KAAK,YAAY,CAAG,CAAC,GAGtE,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,CAAE,KAAK,YAAY,CAAG,CAAC,CAExE,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,EACF,EAAc,SAAW,EAAc,SAAS,EAChD,CAAC,GAAW,CAAC,CAAC,CACrB,CAEA,YAAsB,CACpB,GAAM,CAAE,aAAY,iBAAkB,KAAK,MAC3C,MAAO,CAAC,EAAE,GACJ,GAAiB,EAAc,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,EACxH,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,EAAK,GAAgB,GACnF,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"}
|