@ahrowe/ui 0.39.1 → 0.41.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/README.md +15 -14
- package/dist/cjs-types/common/ahroweProvider/ahroweProvider.d.ts +4 -0
- package/dist/cjs-types/common/ahroweProvider/ahroweProvider.types.d.ts +12 -0
- package/dist/cjs-types/common/ahroweProvider/index.d.ts +2 -0
- package/dist/cjs-types/common/bodyEnd/portalHostContext.d.ts +6 -0
- package/dist/cjs-types/common/calendar/calendar.d.ts +4 -0
- package/dist/cjs-types/common/calendar/calendar.types.d.ts +141 -0
- package/dist/cjs-types/common/calendar/components/agendaList/agendaList.d.ts +5 -0
- package/dist/cjs-types/common/calendar/components/agendaList/agendaList.types.d.ts +23 -0
- package/dist/cjs-types/common/calendar/components/agendaList/index.d.ts +1 -0
- package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.d.ts +4 -0
- package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +17 -0
- package/dist/cjs-types/common/calendar/components/calendarHeader/index.d.ts +1 -0
- package/dist/cjs-types/common/calendar/components/compactMonth/compactMonth.d.ts +9 -0
- package/dist/cjs-types/common/calendar/components/compactMonth/compactMonth.types.d.ts +1 -0
- package/dist/cjs-types/common/calendar/components/compactMonth/index.d.ts +1 -0
- package/dist/cjs-types/common/calendar/components/monthView/index.d.ts +1 -0
- package/dist/cjs-types/common/calendar/components/monthView/monthView.d.ts +5 -0
- package/dist/cjs-types/common/calendar/components/monthView/monthView.types.d.ts +10 -0
- package/dist/cjs-types/common/calendar/components/timeGrid/index.d.ts +1 -0
- package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.d.ts +5 -0
- package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.types.d.ts +40 -0
- package/dist/cjs-types/common/calendar/dates.d.ts +50 -0
- package/dist/cjs-types/common/calendar/format.d.ts +32 -0
- package/dist/cjs-types/common/calendar/gesture.d.ts +32 -0
- package/dist/cjs-types/common/calendar/index.d.ts +2 -0
- package/dist/cjs-types/common/calendar/layout.d.ts +74 -0
- package/dist/cjs-types/common/calendar/useGestures.d.ts +37 -0
- package/dist/cjs-types/common/calendar/usePager.d.ts +20 -0
- package/dist/cjs-types/common/calendar/view.types.d.ts +26 -0
- package/dist/cjs-types/common/configProvider/configProvider.types.d.ts +3 -0
- package/dist/cjs-types/common/confirmModal/confirmModal.types.d.ts +1 -1
- package/dist/cjs-types/common/datePicker/index.d.ts +1 -1
- package/dist/cjs-types/common/errorBoundary/errorBoundary.types.d.ts +2 -2
- package/dist/cjs-types/common/modal/modal.types.d.ts +4 -3
- package/dist/cjs-types/common/themeProvider/index.d.ts +1 -1
- package/dist/cjs-types/common/themeProvider/theme.types.d.ts +16 -0
- package/dist/cjs-types/common/themeProvider/themeProvider.d.ts +7 -9
- package/dist/cjs-types/common/themeProvider/themeVariablesContext.d.ts +2 -2
- package/dist/cjs-types/common/toast/index.d.ts +1 -2
- package/dist/cjs-types/common/toast/toast.types.d.ts +4 -4
- package/dist/cjs-types/common/toast/toastHost.d.ts +4 -0
- package/dist/cjs-types/common/toast/toastService.d.ts +1 -1
- package/dist/cjs-types/common/utils/day.d.ts +8 -0
- package/dist/cjs-types/common/virtualList/useColumns.d.ts +3 -1
- package/dist/cjs-types/index.d.ts +4 -1
- package/dist/esm/common/ahroweProvider/ahroweProvider.mjs +2 -0
- package/dist/esm/common/ahroweProvider/ahroweProvider.mjs.map +1 -0
- package/dist/esm/common/bodyEnd/bodyEnd.mjs +1 -1
- package/dist/esm/common/bodyEnd/bodyEnd.mjs.map +1 -1
- package/dist/esm/common/bodyEnd/portalHostContext.mjs +2 -0
- package/dist/esm/common/bodyEnd/portalHostContext.mjs.map +1 -0
- package/dist/esm/common/calendar/calendar.mjs +2 -0
- package/dist/esm/common/calendar/calendar.mjs.map +1 -0
- package/dist/esm/common/calendar/calendar.module.mjs +2 -0
- package/dist/esm/common/calendar/calendar.module.mjs.map +1 -0
- package/dist/esm/common/calendar/calendar.types.mjs +2 -0
- package/dist/esm/common/calendar/calendar.types.mjs.map +1 -0
- package/dist/esm/common/calendar/components/agendaList/agendaList.mjs +2 -0
- package/dist/esm/common/calendar/components/agendaList/agendaList.mjs.map +1 -0
- package/dist/esm/common/calendar/components/agendaList/agendaList.module.mjs +2 -0
- package/dist/esm/common/calendar/components/agendaList/agendaList.module.mjs.map +1 -0
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs +2 -0
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs.map +1 -0
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs +2 -0
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs.map +1 -0
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs +2 -0
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs.map +1 -0
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs +2 -0
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs.map +1 -0
- package/dist/esm/common/calendar/components/monthView/monthView.mjs +2 -0
- package/dist/esm/common/calendar/components/monthView/monthView.mjs.map +1 -0
- package/dist/esm/common/calendar/components/monthView/monthView.module.mjs +2 -0
- package/dist/esm/common/calendar/components/monthView/monthView.module.mjs.map +1 -0
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs +2 -0
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs.map +1 -0
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs +2 -0
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs.map +1 -0
- package/dist/esm/common/calendar/dates.mjs +2 -0
- package/dist/esm/common/calendar/dates.mjs.map +1 -0
- package/dist/esm/common/calendar/format.mjs +2 -0
- package/dist/esm/common/calendar/format.mjs.map +1 -0
- package/dist/esm/common/calendar/gesture.mjs +2 -0
- package/dist/esm/common/calendar/gesture.mjs.map +1 -0
- package/dist/esm/common/calendar/layout.mjs +2 -0
- package/dist/esm/common/calendar/layout.mjs.map +1 -0
- package/dist/esm/common/calendar/pager.module.mjs +2 -0
- package/dist/esm/common/calendar/pager.module.mjs.map +1 -0
- package/dist/esm/common/calendar/useGestures.mjs +2 -0
- package/dist/esm/common/calendar/useGestures.mjs.map +1 -0
- package/dist/esm/common/calendar/usePager.mjs +2 -0
- package/dist/esm/common/calendar/usePager.mjs.map +1 -0
- package/dist/esm/common/carousel/carousel.module.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/datePicker/components/datePickerMonth/datePickerMonth.mjs +1 -1
- package/dist/esm/common/datePicker/dateFunctions.mjs +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs +1 -1
- package/dist/esm/common/errorBoundary/errorBoundary.mjs +2 -2
- package/dist/esm/common/hooks/useAnchorTracking.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/modal/modal.mjs +1 -1
- package/dist/esm/common/modal/modal.mjs.map +1 -1
- package/dist/esm/common/popover/popover.mjs +1 -1
- package/dist/esm/common/popover/popover.mjs.map +1 -1
- package/dist/esm/common/scrollFade/scrollFade.mjs +1 -1
- package/dist/esm/common/scrollbarProvider/scrollbarProvider.module.mjs.map +1 -1
- package/dist/esm/common/tabHeader/tabHeader.module.mjs.map +1 -1
- package/dist/esm/common/themeProvider/themeProvider.mjs +1 -1
- package/dist/esm/common/themeProvider/themeProvider.mjs.map +1 -1
- package/dist/esm/common/themeProvider/themeVariablesContext.mjs.map +1 -1
- package/dist/esm/common/toast/toastHost.mjs +2 -0
- package/dist/esm/common/toast/toastHost.mjs.map +1 -0
- package/dist/esm/common/toast/toastService.mjs +1 -1
- package/dist/esm/common/toast/toastService.mjs.map +1 -1
- package/dist/esm/common/tooltip/tooltip.module.mjs.map +1 -1
- package/dist/esm/common/utils/day.mjs +1 -1
- package/dist/esm/common/utils/day.mjs.map +1 -1
- package/dist/esm/common/virtualList/useColumns.mjs +1 -1
- package/dist/esm/common/virtualList/useColumns.mjs.map +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/mcp.js +2 -2
- package/dist/style.css +1 -1
- package/dist/types/common/ahroweProvider/ahroweProvider.d.ts +4 -0
- package/dist/types/common/ahroweProvider/ahroweProvider.types.d.ts +12 -0
- package/dist/types/common/ahroweProvider/index.d.ts +2 -0
- package/dist/types/common/bodyEnd/portalHostContext.d.ts +6 -0
- package/dist/types/common/calendar/calendar.d.ts +4 -0
- package/dist/types/common/calendar/calendar.types.d.ts +141 -0
- package/dist/types/common/calendar/components/agendaList/agendaList.d.ts +5 -0
- package/dist/types/common/calendar/components/agendaList/agendaList.types.d.ts +23 -0
- package/dist/types/common/calendar/components/agendaList/index.d.ts +1 -0
- package/dist/types/common/calendar/components/calendarHeader/calendarHeader.d.ts +4 -0
- package/dist/types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +17 -0
- package/dist/types/common/calendar/components/calendarHeader/index.d.ts +1 -0
- package/dist/types/common/calendar/components/compactMonth/compactMonth.d.ts +9 -0
- package/dist/types/common/calendar/components/compactMonth/compactMonth.types.d.ts +1 -0
- package/dist/types/common/calendar/components/compactMonth/index.d.ts +1 -0
- package/dist/types/common/calendar/components/monthView/index.d.ts +1 -0
- package/dist/types/common/calendar/components/monthView/monthView.d.ts +5 -0
- package/dist/types/common/calendar/components/monthView/monthView.types.d.ts +10 -0
- package/dist/types/common/calendar/components/timeGrid/index.d.ts +1 -0
- package/dist/types/common/calendar/components/timeGrid/timeGrid.d.ts +5 -0
- package/dist/types/common/calendar/components/timeGrid/timeGrid.types.d.ts +40 -0
- package/dist/types/common/calendar/dates.d.ts +50 -0
- package/dist/types/common/calendar/format.d.ts +32 -0
- package/dist/types/common/calendar/gesture.d.ts +32 -0
- package/dist/types/common/calendar/index.d.ts +2 -0
- package/dist/types/common/calendar/layout.d.ts +74 -0
- package/dist/types/common/calendar/useGestures.d.ts +37 -0
- package/dist/types/common/calendar/usePager.d.ts +20 -0
- package/dist/types/common/calendar/view.types.d.ts +26 -0
- package/dist/types/common/configProvider/configProvider.types.d.ts +3 -0
- package/dist/types/common/confirmModal/confirmModal.types.d.ts +1 -1
- package/dist/types/common/datePicker/index.d.ts +1 -1
- package/dist/types/common/errorBoundary/errorBoundary.types.d.ts +2 -2
- package/dist/types/common/modal/modal.types.d.ts +4 -3
- package/dist/types/common/themeProvider/index.d.ts +1 -1
- package/dist/types/common/themeProvider/theme.types.d.ts +16 -0
- package/dist/types/common/themeProvider/themeProvider.d.ts +7 -9
- package/dist/types/common/themeProvider/themeVariablesContext.d.ts +2 -2
- package/dist/types/common/toast/index.d.ts +1 -2
- package/dist/types/common/toast/toast.types.d.ts +4 -4
- package/dist/types/common/toast/toastHost.d.ts +4 -0
- package/dist/types/common/toast/toastService.d.ts +1 -1
- package/dist/types/common/utils/day.d.ts +8 -0
- package/dist/types/common/virtualList/useColumns.d.ts +3 -1
- package/dist/types/index.d.ts +4 -1
- package/docs/AhroweProvider.md +90 -0
- package/docs/BodyEnd.md +5 -12
- package/docs/Breadcrumb.md +0 -2
- package/docs/CLAUDE.md +21 -16
- package/docs/Calendar.md +184 -0
- package/docs/CommandPalette.md +0 -2
- package/docs/ConfigProvider.md +12 -8
- package/docs/ConfirmModal.md +1 -3
- package/docs/DatePicker.md +9 -2
- package/docs/ErrorBoundary.md +5 -3
- package/docs/FormValidatorGroup.md +1 -1
- package/docs/KlipyPicker.md +1 -1
- package/docs/Menu.md +0 -2
- package/docs/Modal.md +2 -4
- package/docs/MultiSelect.md +0 -2
- package/docs/OtpInput.md +0 -2
- package/docs/Popover.md +0 -2
- package/docs/RadioGroup.md +1 -1
- package/docs/ScrollbarProvider.md +4 -0
- package/docs/SplitButton.md +0 -2
- package/docs/ThemeProvider.md +13 -10
- package/docs/TimeInput.md +2 -0
- package/docs/Toast.md +18 -17
- package/docs/Tooltip.md +1 -1
- package/docs/VirtualList.md +0 -2
- package/package.json +1 -1
- package/dist/cjs-types/common/toast/toastProvider.d.ts +0 -8
- package/dist/esm/common/toast/toastProvider.mjs +0 -2
- package/dist/esm/common/toast/toastProvider.mjs.map +0 -1
- package/dist/types/common/toast/toastProvider.d.ts +0 -8
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{
|
|
1
|
+
"use client";import{defaultTheme as e}from"./defaultTheme.mjs";import{ThemeVariablesContext as t}from"./themeVariablesContext.mjs";import n from"./theme.module.mjs";import r,{Component as i}from"react";import a from"classnames";import{jsx as o}from"react/jsx-runtime";function s(e,t){let n=e.find(e=>e.id===t);return n?[...n.baseThemeId?s(e,n.baseThemeId):[],n.variables]:[]}function c({themes:t=[e],currentThemeId:n}){let r=t.find(e=>!e.baseThemeId)??t[0],i=r?r.variables:{},a=n?s(t,n):[];return Object.assign({},i,...a)}var l=class extends i{constructor(...e){super(...e),this.state={resolvedVariables:c(this.props),colorFadeActive:!1,currentThemeColor:null,resolvedFrom:{themes:this.props.themes,currentThemeId:this.props.currentThemeId}},this.colorFadeTimeout=null,this.wrapperRef=r.createRef(),this.themeColorMeta=null,this.createdThemeColorMeta=!1}static{this.contextType=t}static getDerivedStateFromProps(e,t){let{themes:n,currentThemeId:r}=t.resolvedFrom;return e.themes===n&&e.currentThemeId===r?null:{resolvedVariables:c(e),colorFadeActive:!0,resolvedFrom:{themes:e.themes,currentThemeId:e.currentThemeId}}}componentDidMount(){this.readThemeColor()}componentDidUpdate(e,t){t.resolvedVariables!==this.state.resolvedVariables&&(this.readThemeColor(),this.colorFadeTimeout&&clearTimeout(this.colorFadeTimeout),this.colorFadeTimeout=setTimeout(()=>{this.setState({colorFadeActive:!1}),this.colorFadeTimeout=null},500)),t.currentThemeColor!==this.state.currentThemeColor&&this.syncThemeColorMeta(this.state.currentThemeColor??``)}componentWillUnmount(){this.colorFadeTimeout&&clearTimeout(this.colorFadeTimeout),this.createdThemeColorMeta&&=(this.themeColorMeta?.remove(),this.themeColorMeta=null,!1)}syncThemeColorMeta(e){if(typeof document<`u`){if(!this.themeColorMeta){let e=document.head.querySelector(`meta[name="theme-color"]`);if(e)this.themeColorMeta=e;else{let e=document.createElement(`meta`);e.setAttribute(`name`,`theme-color`),document.head.appendChild(e),this.themeColorMeta=e,this.createdThemeColorMeta=!0}}this.themeColorMeta.setAttribute(`content`,e)}}readThemeColor(){if(this.context||!this.wrapperRef.current)return;let e=getComputedStyle(this.wrapperRef.current).getPropertyValue(`--primary-color`).trim();e!==this.state.currentThemeColor&&this.setState({currentThemeColor:e})}render(){let{children:e}=this.props,{resolvedVariables:r,colorFadeActive:i}=this.state;return o(`div`,{ref:this.wrapperRef,id:`themeProvider`,className:a(n.themeRoot,i&&n.colorFade),style:r,children:o(t.Provider,{value:r,children:e})})}};export{l as default};
|
|
2
2
|
//# sourceMappingURL=themeProvider.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themeProvider.mjs","names":[],"sources":["../../../../package/common/themeProvider/themeProvider.tsx"],"sourcesContent":["import React, { Component } from 'react';\nimport cx from 'classnames';\n\nimport type { Theme } from './theme.types';\nimport { defaultTheme } from './defaultTheme';\nimport { ThemeVariablesContext } from './themeVariablesContext';\nimport styles from './theme.module.pcss';\n\ninterface
|
|
1
|
+
{"version":3,"file":"themeProvider.mjs","names":[],"sources":["../../../../package/common/themeProvider/themeProvider.tsx"],"sourcesContent":["import React, { Component } from 'react';\nimport cx from 'classnames';\n\nimport type { Theme, ThemeProviderProps } from './theme.types';\nimport { defaultTheme } from './defaultTheme';\nimport { ThemeVariablesContext } from './themeVariablesContext';\nimport styles from './theme.module.pcss';\n\ninterface State {\n resolvedVariables: Record<string, string>;\n colorFadeActive: boolean;\n currentThemeColor: string | null;\n /** What `resolvedVariables` was resolved from, to tell a theme change from any other render. */\n resolvedFrom: { themes: Theme[] | undefined; currentThemeId: string | undefined };\n}\n\n/**\n * Resolves a theme ID's variables by walking up its baseThemeId chain, ordered from deepest\n * ancestor to the requested theme so they merge in order (later entries win).\n */\nfunction resolveChain(themes: Theme[], id: string): Record<string, string>[] {\n const theme = themes.find((t) => t.id === id);\n if (!theme) return [];\n const parentVars = theme.baseThemeId ? resolveChain(themes, theme.baseThemeId) : [];\n return [...parentVars, theme.variables as Record<string, string>];\n}\n\nfunction resolveVariables({ themes = [defaultTheme], currentThemeId }: ThemeProviderProps): Record<string, string> {\n // The root theme, the first without a baseThemeId, is always the foundation.\n const rootTheme = themes.find((t) => !t.baseThemeId) ?? themes[0];\n const rootVars = rootTheme ? (rootTheme.variables as Record<string, string>) : {};\n const chainVars = currentThemeId ? resolveChain(themes, currentThemeId) : [];\n return Object.assign({}, rootVars, ...chainVars);\n}\n\nclass ThemeProvider extends Component<ThemeProviderProps, State> {\n // A nested provider themes a section, not the page, so it leaves the page's `theme-color` alone.\n static contextType = ThemeVariablesContext;\n declare context: React.ContextType<typeof ThemeVariablesContext>;\n\n // Resolved before the first render rather than after mount: resolved in componentDidMount, every\n // component rendered and measured itself unthemed first, and on each page load some 50\n // backgrounds then faded in from nothing.\n state: State = {\n resolvedVariables: resolveVariables(this.props),\n colorFadeActive: false,\n currentThemeColor: null,\n resolvedFrom: { themes: this.props.themes, currentThemeId: this.props.currentThemeId },\n };\n\n private colorFadeTimeout: ReturnType<typeof setTimeout> | null = null;\n private wrapperRef = React.createRef<HTMLDivElement>();\n private themeColorMeta: HTMLMetaElement | null = null;\n private createdThemeColorMeta = false;\n\n // The fade and the new variables have to land in the same render: added a render later, the\n // browser may already have painted the new colours without it.\n static getDerivedStateFromProps(props: ThemeProviderProps, state: State): Partial<State> | null {\n const { themes, currentThemeId } = state.resolvedFrom;\n if (props.themes === themes && props.currentThemeId === currentThemeId) return null;\n return {\n resolvedVariables: resolveVariables(props),\n colorFadeActive: true,\n resolvedFrom: { themes: props.themes, currentThemeId: props.currentThemeId },\n };\n }\n\n componentDidMount() {\n this.readThemeColor();\n }\n\n componentDidUpdate(prevProps: ThemeProviderProps, prevState: State) {\n if (prevState.resolvedVariables !== this.state.resolvedVariables) {\n this.readThemeColor();\n if (this.colorFadeTimeout) clearTimeout(this.colorFadeTimeout);\n this.colorFadeTimeout = setTimeout(() => {\n this.setState({ colorFadeActive: false });\n this.colorFadeTimeout = null;\n }, 500);\n }\n if (prevState.currentThemeColor !== this.state.currentThemeColor) {\n this.syncThemeColorMeta(this.state.currentThemeColor ?? '');\n }\n }\n\n componentWillUnmount() {\n if (this.colorFadeTimeout) clearTimeout(this.colorFadeTimeout);\n // Only remove the meta tag if we created it; leave a host-app tag intact.\n // Also clear the cached refs — StrictMode's dev-only mount/unmount/remount\n // cycle reuses this instance, and a stale ref would otherwise point at a\n // detached element on remount instead of re-inserting into <head>.\n if (this.createdThemeColorMeta) {\n this.themeColorMeta?.remove();\n this.themeColorMeta = null;\n this.createdThemeColorMeta = false;\n }\n }\n\n /**\n * Replaces the former react-helmet usage: keep a single\n * <meta name=\"theme-color\"> in sync with the active theme's primary colour.\n * Reuses a tag the host app already declares; otherwise creates its own\n * (and removes it again on unmount).\n */\n private syncThemeColorMeta(color: string) {\n if (typeof document === 'undefined') return;\n\n if (!this.themeColorMeta) {\n const existing = document.head.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]');\n if (existing) {\n this.themeColorMeta = existing;\n } else {\n const meta = document.createElement('meta');\n meta.setAttribute('name', 'theme-color');\n document.head.appendChild(meta);\n this.themeColorMeta = meta;\n this.createdThemeColorMeta = true;\n }\n }\n\n this.themeColorMeta.setAttribute('content', color);\n }\n\n /** `--primary-color` as the browser resolved it, which may be a `var()` of another variable. */\n private readThemeColor() {\n if (this.context || !this.wrapperRef.current) return;\n const color = getComputedStyle(this.wrapperRef.current).getPropertyValue('--primary-color').trim();\n if (color !== this.state.currentThemeColor) this.setState({ currentThemeColor: color });\n }\n\n render() {\n const { children } = this.props;\n const { resolvedVariables, colorFadeActive } = this.state;\n\n return (\n <div\n ref={this.wrapperRef}\n id='themeProvider'\n className={cx(styles.themeRoot, colorFadeActive && styles.colorFade)}\n style={resolvedVariables as React.CSSProperties}\n >\n <ThemeVariablesContext.Provider value={resolvedVariables}>{children}</ThemeVariablesContext.Provider>\n </div>\n );\n }\n}\n\nexport default ThemeProvider;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themeVariablesContext.mjs","names":[],"sources":["../../../../package/common/themeProvider/themeVariablesContext.ts"],"sourcesContent":["import { createContext } from 'react';\n\n/**\n * The nearest ThemeProvider's resolved variables, for content that renders outside its DOM\n * subtree. Theme variables reach a component by CSS inheritance, which a portal breaks: a\n * `BodyEnd` child lands wherever
|
|
1
|
+
{"version":3,"file":"themeVariablesContext.mjs","names":[],"sources":["../../../../package/common/themeProvider/themeVariablesContext.ts"],"sourcesContent":["import { createContext } from 'react';\n\n/**\n * The nearest ThemeProvider's resolved variables, for content that renders outside its DOM\n * subtree. Theme variables reach a component by CSS inheritance, which a portal breaks: a\n * `BodyEnd` child lands wherever the portal target is, so it picks up whatever provider wraps\n * *that* node rather than the one it was written under.\n *\n * Deliberately its own module rather than a member of `themeProvider.tsx`: BodyEnd needs the\n * context and nothing else, and importing the component for it would pull the whole\n * ThemeProvider into every bundle that uses a portal.\n */\nexport const ThemeVariablesContext = createContext<Record<string, string> | null>(null);\n"],"mappings":"mDAYA,IAAa,EAAwB,EAA6C,IAAI"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import e from"../bodyEnd/bodyEnd.mjs";import t from"./toast.module.mjs";import n from"./toast.mjs";import{_registerToastHandler as r,_unregisterToastHandler as i}from"./toastService.mjs";import{useCallback as a,useInsertionEffect as o,useRef as s,useState as c}from"react";import l from"classnames";import{Fragment as u,jsx as d,jsxs as f}from"react/jsx-runtime";var p={position:`top-right`,duration:4e3,showRemainingTime:!0,showCloseButton:!0,allowStacking:!0,pauseOnHover:!0,labels:{close:`Close`}},m=220;function h(e){return t[`container-${e}`]}function g({children:g,position:_=p.position,duration:v=p.duration,showRemainingTime:y=p.showRemainingTime,showCloseButton:b=p.showCloseButton,allowStacking:x=p.allowStacking,pauseOnHover:S=p.pauseOnHover,labels:C}){let[w,T]=c([]),E=s(0),D=a(e=>{T(t=>t.map(t=>t.id===e?{...t,dismissing:!0}:t)),setTimeout(()=>{T(t=>t.filter(t=>t.id!==e))},m)},[]),O=a((e,t)=>{let n={position:t?.position??_,duration:t?.duration??v,showRemainingTime:t?.showRemainingTime??y,showCloseButton:t?.showCloseButton??b,pauseOnHover:t?.pauseOnHover??S,type:t?.type??`default`,classNames:t?.classNames,styles:t?.styles};E.current+=1;let r={id:`toast-${E.current}`,content:e,options:n,dismissing:!1,labels:t?.labels};T(e=>!x&&e.length>0?(setTimeout(()=>{T([r])},m),e.map(e=>({...e,dismissing:!0}))):[...e,r])},[_,v,y,b,x,S]),k=s(O);o(()=>{k.current=O},[O]),o(()=>{let e=(e,t)=>k.current(e,t);return r(e),()=>i(e)},[]);let A=w.reduce((e,t)=>{let n=t.options.position;return e[n]||(e[n]=[]),e[n].push(t),e},{});return f(u,{children:[g,d(e,{children:Object.entries(A).map(([e,r])=>d(`div`,{className:l(t.container,h(e)),children:r.map(t=>d(n,{item:t,isBottom:e.startsWith(`bottom`),onDismiss:D,labels:{...p.labels,...C,...t.labels}},t.id))},e))})]})}export{g as default};
|
|
2
|
+
//# sourceMappingURL=toastHost.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toastHost.mjs","names":[],"sources":["../../../../package/common/toast/toastHost.tsx"],"sourcesContent":["import React, { useCallback, useInsertionEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './toast.module.pcss';\nimport Toast from './toast';\nimport { _registerToastHandler, _unregisterToastHandler } from './toastService';\nimport type {\n ToastContextConfig,\n ToastItem,\n ToastOptions,\n ResolvedToastOptions,\n ToastPosition,\n ToastLabels,\n ToastHostProps,\n} from './toast.types';\nimport type { ReactNode } from 'react';\n\nconst DEFAULTS: Required<ToastContextConfig> = {\n position: 'top-right',\n duration: 4000,\n showRemainingTime: true,\n showCloseButton: true,\n allowStacking: true,\n pauseOnHover: true,\n labels: { close: 'Close' },\n};\n\nconst DISMISS_ANIMATION_MS = 220;\n\nfunction positionToClass(position: ToastPosition): string {\n return styles[`container-${position}`];\n}\n\nfunction ToastHost({\n children,\n position = DEFAULTS.position,\n duration = DEFAULTS.duration,\n showRemainingTime = DEFAULTS.showRemainingTime,\n showCloseButton = DEFAULTS.showCloseButton,\n allowStacking = DEFAULTS.allowStacking,\n pauseOnHover = DEFAULTS.pauseOnHover,\n labels,\n}: ToastHostProps) {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const counterRef = useRef(0);\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) => prev.map((t) => (t.id === id ? { ...t, dismissing: true } : t)));\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, DISMISS_ANIMATION_MS);\n }, []);\n\n const addToast = useCallback(\n (content: ReactNode, options?: ToastOptions) => {\n const resolved: ResolvedToastOptions = {\n position: options?.position ?? position,\n duration: options?.duration ?? duration,\n showRemainingTime: options?.showRemainingTime ?? showRemainingTime,\n showCloseButton: options?.showCloseButton ?? showCloseButton,\n pauseOnHover: options?.pauseOnHover ?? pauseOnHover,\n type: options?.type ?? 'default',\n classNames: options?.classNames,\n styles: options?.styles,\n };\n\n counterRef.current += 1;\n const id = `toast-${counterRef.current}`;\n const newToast: ToastItem = { id, content, options: resolved, dismissing: false, labels: options?.labels };\n\n setToasts((prev) => {\n if (!allowStacking && prev.length > 0) {\n // Mark all existing as dismissing, then replace\n setTimeout(() => {\n setToasts([newToast]);\n }, DISMISS_ANIMATION_MS);\n return prev.map((t) => ({ ...t, dismissing: true }));\n }\n return [...prev, newToast];\n });\n },\n [position, duration, showRemainingTime, showCloseButton, allowStacking, pauseOnHover],\n );\n\n // Insertion effects run before every layout and passive effect, including the app's, which as\n // this host's descendants would otherwise run first. Registered once, so that a settings change\n // does not move this host to the end of the list.\n const latestAddToast = useRef(addToast);\n useInsertionEffect(() => {\n latestAddToast.current = addToast;\n }, [addToast]);\n\n useInsertionEffect(() => {\n const show: typeof addToast = (content, options) => latestAddToast.current(content, options);\n _registerToastHandler(show);\n return () => _unregisterToastHandler(show);\n }, []);\n\n // Group toasts by position so per-toast position overrides work correctly\n const byPosition = toasts.reduce<Record<string, ToastItem[]>>((acc, t) => {\n const pos = t.options.position;\n if (!acc[pos]) acc[pos] = [];\n acc[pos].push(t);\n return acc;\n }, {});\n\n return (\n <>\n {children}\n <BodyEnd>\n {Object.entries(byPosition).map(([pos, items]) => (\n <div key={pos} className={cx(styles.container, positionToClass(pos as typeof position))}>\n {items.map((item) => (\n <Toast\n key={item.id}\n item={item}\n isBottom={pos.startsWith('bottom')}\n onDismiss={dismiss}\n labels={{ ...DEFAULTS.labels, ...labels, ...item.labels } as Required<ToastLabels>}\n />\n ))}\n </div>\n ))}\n </BodyEnd>\n </>\n );\n}\n\nexport default ToastHost;\n"],"mappings":"wXAkBA,IAAM,EAAyC,CAC7C,SAAU,YACV,SAAU,IACV,kBAAmB,GACnB,gBAAiB,GACjB,cAAe,GACf,aAAc,GACd,OAAQ,CAAE,MAAO,OAAQ,CAC3B,EAEM,EAAuB,IAE7B,SAAS,EAAgB,EAAiC,CACxD,OAAO,EAAO,aAAa,IAC7B,CAEA,SAAS,EAAU,CACjB,WACA,WAAW,EAAS,SACpB,WAAW,EAAS,SACpB,oBAAoB,EAAS,kBAC7B,kBAAkB,EAAS,gBAC3B,gBAAgB,EAAS,cACzB,eAAe,EAAS,aACxB,UACiB,CACjB,GAAM,CAAC,EAAQ,GAAa,EAAsB,CAAC,CAAC,EAC9C,EAAa,EAAO,CAAC,EAErB,EAAU,EAAa,GAAe,CAC1C,EAAW,GAAS,EAAK,IAAK,GAAO,EAAE,KAAO,EAAK,CAAE,GAAG,EAAG,WAAY,EAAK,EAAI,CAAE,CAAC,EACnF,eAAiB,CACf,EAAW,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAO,CAAE,CAAC,CACrD,EAAG,CAAoB,CACzB,EAAG,CAAC,CAAC,EAEC,EAAW,GACd,EAAoB,IAA2B,CAC9C,IAAM,EAAiC,CACrC,SAAU,GAAS,UAAY,EAC/B,SAAU,GAAS,UAAY,EAC/B,kBAAmB,GAAS,mBAAqB,EACjD,gBAAiB,GAAS,iBAAmB,EAC7C,aAAc,GAAS,cAAgB,EACvC,KAAM,GAAS,MAAQ,UACvB,WAAY,GAAS,WACrB,OAAQ,GAAS,MACnB,EAEA,EAAW,SAAW,EAEtB,IAAM,EAAsB,CAAE,GAAA,SADV,EAAW,UACG,UAAS,QAAS,EAAU,WAAY,GAAO,OAAQ,GAAS,MAAO,EAEzG,EAAW,GACL,CAAC,GAAiB,EAAK,OAAS,GAElC,eAAiB,CACf,EAAU,CAAC,CAAQ,CAAC,CACtB,EAAG,CAAoB,EAChB,EAAK,IAAK,IAAO,CAAE,GAAG,EAAG,WAAY,EAAK,EAAE,GAE9C,CAAC,GAAG,EAAM,CAAQ,CAC1B,CACH,EACA,CAAC,EAAU,EAAU,EAAmB,EAAiB,EAAe,CAAY,CACtF,EAKM,EAAiB,EAAO,CAAQ,EACtC,MAAyB,CACvB,EAAe,QAAU,CAC3B,EAAG,CAAC,CAAQ,CAAC,EAEb,MAAyB,CACvB,IAAM,GAAyB,EAAS,IAAY,EAAe,QAAQ,EAAS,CAAO,EAE3F,OADA,EAAsB,CAAI,MACb,EAAwB,CAAI,CAC3C,EAAG,CAAC,CAAC,EAGL,IAAM,EAAa,EAAO,QAAqC,EAAK,IAAM,CACxE,IAAM,EAAM,EAAE,QAAQ,SAGtB,OAFK,EAAI,KAAM,EAAI,GAAO,CAAC,GAC3B,EAAI,EAAI,CAAC,KAAK,CAAC,EACR,CACT,EAAG,CAAC,CAAC,EAEL,OACE,EAAA,EAAA,CAAA,SAAA,CACG,EACD,EAAC,EAAD,CAAA,SACG,OAAO,QAAQ,CAAU,CAAC,CAAC,KAAK,CAAC,EAAK,KACrC,EAAC,MAAD,CAAe,UAAW,EAAG,EAAO,UAAW,EAAgB,CAAsB,CAAC,EACnF,SAAA,EAAM,IAAK,GACV,EAAC,EAAD,CAEQ,OACN,SAAU,EAAI,WAAW,QAAQ,EACjC,UAAW,EACX,OAAQ,CAAE,GAAG,EAAS,OAAQ,GAAG,EAAQ,GAAG,EAAK,MAAO,CACzD,EALM,EAAK,EAKX,CACF,CACE,EAVK,CAUL,CACN,CACM,CAAA,CACT,CAAA,CAAA,CAEN"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e=
|
|
1
|
+
"use client";var e=[];function t(t){e.length>0&&console.warn(`[Toast] More than one outermost AhroweProvider is mounted, and toasts show in only one of them. Keep one at the root and nest any other inside it.`),e.push(t)}function n(t){let n=e.indexOf(t);n!==-1&&e.splice(n,1)}function r(t,n){let r=e[e.length-1];if(!r){console.error(`[Toast] No AhroweProvider found. Wrap your app in <AhroweProvider>.`);return}r(t,n)}export{t as _registerToastHandler,n as _unregisterToastHandler,r as showToast};
|
|
2
2
|
//# sourceMappingURL=toastService.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toastService.mjs","names":[],"sources":["../../../../package/common/toast/toastService.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ToastOptions } from './toast.types';\n\ntype ShowToastFn = (content: ReactNode, options?: ToastOptions) => void;\n\
|
|
1
|
+
{"version":3,"file":"toastService.mjs","names":[],"sources":["../../../../package/common/toast/toastService.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ToastOptions } from './toast.types';\n\ntype ShowToastFn = (content: ReactNode, options?: ToastOptions) => void;\n\n// A list, so that when the host registered last unmounts, the one before it takes over again.\nconst handlers: ShowToastFn[] = [];\n\nexport function _registerToastHandler(fn: ShowToastFn): void {\n if (handlers.length > 0) {\n console.warn(\n '[Toast] More than one outermost AhroweProvider is mounted, and toasts show in only one of them. Keep one at the root and nest any other inside it.',\n );\n }\n handlers.push(fn);\n}\n\nexport function _unregisterToastHandler(fn: ShowToastFn): void {\n const index = handlers.indexOf(fn);\n if (index !== -1) handlers.splice(index, 1);\n}\n\nexport function showToast(content: ReactNode, options?: ToastOptions): void {\n const handler = handlers[handlers.length - 1];\n if (!handler) {\n console.error('[Toast] No AhroweProvider found. Wrap your app in <AhroweProvider>.');\n return;\n }\n handler(content, options);\n}\n"],"mappings":"aAMA,IAAM,EAA0B,CAAC,EAEjC,SAAgB,EAAsB,EAAuB,CACvD,EAAS,OAAS,GACpB,QAAQ,KACN,oJACF,EAEF,EAAS,KAAK,CAAE,CAClB,CAEA,SAAgB,EAAwB,EAAuB,CAC7D,IAAM,EAAQ,EAAS,QAAQ,CAAE,EAC7B,IAAU,IAAI,EAAS,OAAO,EAAO,CAAC,CAC5C,CAEA,SAAgB,EAAU,EAAoB,EAA8B,CAC1E,IAAM,EAAU,EAAS,EAAS,OAAS,GAC3C,GAAI,CAAC,EAAS,CACZ,QAAQ,MAAM,qEAAqE,EACnF,MACF,CACA,EAAQ,EAAS,CAAO,CAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.module.mjs","names":[],"sources":["../../../../package/common/tooltip/tooltip.module.pcss"],"sourcesContent":["/* Both bubbles are portaled to the end of the document and placed by\n `usePopoverPosition`, which writes `top`, `left`, `visibility` and\n `data-placement` straight onto them. */\n.tooltipBubble,\n.tooltipError {\n position: fixed;\n z-index: 10;\n width: max-content;\n\n /* So a max-width is the width you actually get, padding included. Without it the\n screen cap below let the box out by its own padding. */\n box-sizing: border-box;\n\n /* Hidden until the first coordinates are written, to avoid a top-left flash. */\n visibility: hidden;\n}\n\n.tooltipBubble {\n /* Resolved on the bubble so it, its arrow and the badge cannot drift apart. The\n default is an inverse of the theme, not a fixed slate: a tooltip has to separate\n from the page it floats over, and a dark bubble sat almost invisibly on a dark\n theme. */\n --custom-tooltip-background: var(--tooltip-background, color-mix(in oklab, var(--text-color) 82%, var(--background)));\n --custom-tooltip-color: var(--tooltip-color, var(--background));\n\n /* The lengths here are em against this bubble's own 0.75em, so the ratios are of 12px,\n not 16, and max-width is a line measure rather than a pixel cap. */\n border-radius: 0.25em;\n\n /* Padding included, per the border-box above. The second term is the screen, with\n the gutter `usePopoverPosition` keeps when it shifts a panel back on-screen: a\n bubble wider than that cannot be clamped into view, only pushed off one edge,\n so it wraps instead. */\n max-width: min(16.667em, calc(100vw - 16px));\n font-size: 0.75em;\n background-color: var(--custom-tooltip-background);\n padding: 0.5em 0.75em;\n color: var(--custom-tooltip-color);\n pointer-events: none;\n\n &::after {\n content: '';\n position: absolute;\n top: 100%;\n\n /* The bubble's leading edge is the trigger's, so half the trigger's width is the\n trigger's centre. The second term must stay half the arrow's own width, or it\n stops pointing at it. */\n left: calc(var(--tooltip-trigger-width, 10px) / 2 - 0.4167em);\n border-width: 0.4167em;\n border-style: solid;\n border-color: var(--custom-tooltip-background) transparent transparent;\n }\n\n &[data-placement='bottom']::after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent var(--custom-tooltip-background);\n }\n}\n\n.tooltipDetails {\n /* Repeated from .tooltipBubble above: the badge is a second root, rendered without one. */\n --custom-tooltip-background: var(--tooltip-background, color-mix(in oklab, var(--text-color) 82%, var(--background)));\n --custom-tooltip-color: var(--tooltip-color, var(--background));\n\n position: relative;\n display: inline-flex;\n align-items: center;\n\n &-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n /* The theme's base, not a multiple of the font below: that landed a fraction of a pixel short. */\n width: var(--default-font-size);\n height: var(--default-font-size);\n border-radius: 50%;\n\n /* calc, not em: this badge renders inline wherever the consumer puts it, so em would\n measure that text. The bubble above can use em,
|
|
1
|
+
{"version":3,"file":"tooltip.module.mjs","names":[],"sources":["../../../../package/common/tooltip/tooltip.module.pcss"],"sourcesContent":["/* Both bubbles are portaled to the end of the document and placed by\n `usePopoverPosition`, which writes `top`, `left`, `visibility` and\n `data-placement` straight onto them. */\n.tooltipBubble,\n.tooltipError {\n position: fixed;\n z-index: 10;\n width: max-content;\n\n /* So a max-width is the width you actually get, padding included. Without it the\n screen cap below let the box out by its own padding. */\n box-sizing: border-box;\n\n /* Hidden until the first coordinates are written, to avoid a top-left flash. */\n visibility: hidden;\n}\n\n.tooltipBubble {\n /* Resolved on the bubble so it, its arrow and the badge cannot drift apart. The\n default is an inverse of the theme, not a fixed slate: a tooltip has to separate\n from the page it floats over, and a dark bubble sat almost invisibly on a dark\n theme. */\n --custom-tooltip-background: var(--tooltip-background, color-mix(in oklab, var(--text-color) 82%, var(--background)));\n --custom-tooltip-color: var(--tooltip-color, var(--background));\n\n /* The lengths here are em against this bubble's own 0.75em, so the ratios are of 12px,\n not 16, and max-width is a line measure rather than a pixel cap. */\n border-radius: 0.25em;\n\n /* Padding included, per the border-box above. The second term is the screen, with\n the gutter `usePopoverPosition` keeps when it shifts a panel back on-screen: a\n bubble wider than that cannot be clamped into view, only pushed off one edge,\n so it wraps instead. */\n max-width: min(16.667em, calc(100vw - 16px));\n font-size: 0.75em;\n background-color: var(--custom-tooltip-background);\n padding: 0.5em 0.75em;\n color: var(--custom-tooltip-color);\n pointer-events: none;\n\n &::after {\n content: '';\n position: absolute;\n top: 100%;\n\n /* The bubble's leading edge is the trigger's, so half the trigger's width is the\n trigger's centre. The second term must stay half the arrow's own width, or it\n stops pointing at it. */\n left: calc(var(--tooltip-trigger-width, 10px) / 2 - 0.4167em);\n border-width: 0.4167em;\n border-style: solid;\n border-color: var(--custom-tooltip-background) transparent transparent;\n }\n\n &[data-placement='bottom']::after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent var(--custom-tooltip-background);\n }\n}\n\n.tooltipDetails {\n /* Repeated from .tooltipBubble above: the badge is a second root, rendered without one. */\n --custom-tooltip-background: var(--tooltip-background, color-mix(in oklab, var(--text-color) 82%, var(--background)));\n --custom-tooltip-color: var(--tooltip-color, var(--background));\n\n position: relative;\n display: inline-flex;\n align-items: center;\n\n &-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n /* The theme's base, not a multiple of the font below: that landed a fraction of a pixel short. */\n width: var(--default-font-size);\n height: var(--default-font-size);\n border-radius: 50%;\n\n /* calc, not em: this badge renders inline wherever the consumer puts it, so em would\n measure that text. The bubble above can use em, because BodyEnd sets the theme's own\n font size on everything it portals. */\n font-size: calc(var(--default-font-size) * 0.6875);\n font-weight: 700;\n background-color: var(--custom-tooltip-background);\n color: var(--custom-tooltip-color);\n cursor: default;\n user-select: none;\n }\n}\n\n.tooltipError {\n border-radius: 0.3em;\n\n /* No measure of its own: a validator's message is as long as it is. The screen is\n still the limit, though, the same one the bubble above takes. */\n max-width: calc(100vw - 16px);\n background-color: var(--error-lighter);\n color: var(--error-color);\n font-size: 0.625em;\n padding: 0.6em 0.9em;\n\n &::after {\n content: '';\n position: absolute;\n top: 100%;\n right: 1.2em;\n border-width: 0.5em;\n border-style: solid;\n border-color: var(--error-border-color) transparent transparent transparent;\n }\n\n &[data-placement='bottom']::after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent var(--error-border-color) transparent;\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e=/^(\d{4})-(\d{2})-(\d{2})$/;function t({year:e,month:t}){let n=new Date(0);return n.setUTCFullYear(e,t,0),n.getUTCDate()}function n(n){if(typeof n!=`string`)return null;let r=e.exec(n);if(!r)return null;let i=Number(r[1]),a=Number(r[2]),o=Number(r[3]);return a<1||a>12||o<1||o>t({year:i,month:a})?null:{year:i,month:a,day:o}}function r(e){return n(e)?e:null}function i({year:e,month:t,day:n}){return`${String(e).padStart(4,`0`)}-${String(t).padStart(2,`0`)}-${String(n).padStart(2,`0`)}`}function a(e){return Number.isNaN(e.getTime())?``:i({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate()})}function o(e){let t=n(e);if(!t)return new Date(NaN);let r=new Date(2e3,0,1);return r.setFullYear(t.year,t.month-1,t.day),r}export{r as asDay,a as dateToDay,o as dayToDate,t as daysInMonth,i as formatDay,n as parseDay};
|
|
1
|
+
"use client";var e=/^(\d{4})-(\d{2})-(\d{2})$/;function t({year:e,month:t}){let n=new Date(0);return n.setUTCFullYear(e,t,0),n.getUTCDate()}function n(n){if(typeof n!=`string`)return null;let r=e.exec(n);if(!r)return null;let i=Number(r[1]),a=Number(r[2]),o=Number(r[3]);return a<1||a>12||o<1||o>t({year:i,month:a})?null:{year:i,month:a,day:o}}function r(e){return n(e)?e:null}function i({year:e,month:t,day:n}){return`${String(e).padStart(4,`0`)}-${String(t).padStart(2,`0`)}-${String(n).padStart(2,`0`)}`}function a(e){return Number.isNaN(e.getTime())?``:i({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate()})}function o(e){let t=n(e);if(!t)return new Date(NaN);let r=new Date(2e3,0,1);return r.setFullYear(t.year,t.month-1,t.day),r}var s=/^(\d{2}):(\d{2})$/;function c(e){return Number.isNaN(e.getTime())?``:`${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}`}function l(e,t){let n=o(e),r=s.exec(t),i=r?Number(r[1]):NaN,a=r?Number(r[2]):NaN;return Number.isNaN(n.getTime())||!(i<=23&&a<=59)?new Date(NaN):(n.setHours(i,a,0,0),n)}export{r as asDay,a as dateToDay,c as dateToTime,l as dayTimeToDate,o as dayToDate,t as daysInMonth,i as formatDay,n as parseDay};
|
|
2
2
|
//# sourceMappingURL=day.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"day.mjs","names":[],"sources":["../../../../package/common/utils/day.ts"],"sourcesContent":["// A day is a `'YYYY-MM-DD'` string, the value of `<input type=\"date\">`: no time and no time zone,\n// so it is the same day for everyone. A `Date` is a moment and cannot be one.\n//\n// Dates are built with `setFullYear` rather than the `Date` constructor or `Date.UTC`, which read\n// the years 0 to 99 as 1900 to 1999.\n\nexport interface DayParts {\n year: number;\n /** 1 to 12. */\n month: number;\n day: number;\n}\n\nconst DAY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function daysInMonth({ year, month }: Pick<DayParts, 'year' | 'month'>): number {\n const date = new Date(0);\n date.setUTCFullYear(year, month, 0);\n return date.getUTCDate();\n}\n\n/** The parts of a `'YYYY-MM-DD'` string, or `null` for anything else, 31 February included. */\nexport function parseDay(value: unknown): DayParts | null {\n if (typeof value !== 'string') return null;\n const match = DAY.exec(value);\n if (!match) return null;\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (month < 1 || month > 12 || day < 1 || day > daysInMonth({ year, month })) return null;\n return { year, month, day };\n}\n\n/** `value` itself when it is a `'YYYY-MM-DD'` day that exists, otherwise `null`. */\nexport function asDay(value: unknown): string | null {\n return parseDay(value) ? (value as string) : null;\n}\n\nexport function formatDay({ year, month, day }: DayParts): string {\n return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n}\n\n/** The day `date` falls on in the browser's time zone, as `'YYYY-MM-DD'`; `''` for an Invalid Date. */\nexport function dateToDay(date: Date): string {\n if (Number.isNaN(date.getTime())) return '';\n return formatDay({ year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() });\n}\n\n/** The first moment of a `'YYYY-MM-DD'` day in the browser's time zone. An Invalid Date for anything else. */\nexport function dayToDate(day: string): Date {\n const parts = parseDay(day);\n if (!parts) return new Date(NaN);\n const date = new Date(2000, 0, 1);\n date.setFullYear(parts.year, parts.month - 1, parts.day);\n return date;\n}\n"],"mappings":"aAaA,IAAM,EAAM,4BAEZ,SAAgB,EAAY,CAAE,OAAM,SAAmD,CACrF,IAAM,EAAO,IAAI,KAAK,CAAC,EAEvB,OADA,EAAK,eAAe,EAAM,EAAO,CAAC,EAC3B,EAAK,WAAW,CACzB,CAGA,SAAgB,EAAS,EAAiC,CACxD,GAAI,OAAO,GAAU,SAAU,OAAO,KACtC,IAAM,EAAQ,EAAI,KAAK,CAAK,EAC5B,GAAI,CAAC,EAAO,OAAO,KACnB,IAAM,EAAO,OAAO,EAAM,EAAE,EACtB,EAAQ,OAAO,EAAM,EAAE,EACvB,EAAM,OAAO,EAAM,EAAE,EAE3B,OADI,EAAQ,GAAK,EAAQ,IAAM,EAAM,GAAK,EAAM,EAAY,CAAE,OAAM,OAAM,CAAC,EAAU,KAC9E,CAAE,OAAM,QAAO,KAAI,CAC5B,CAGA,SAAgB,EAAM,EAA+B,CACnD,OAAO,EAAS,CAAK,EAAK,EAAmB,IAC/C,CAEA,SAAgB,EAAU,CAAE,OAAM,QAAO,OAAyB,CAChE,MAAO,GAAG,OAAO,CAAI,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAK,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAG,CAAC,CAAC,SAAS,EAAG,GAAG,GAC1G,CAGA,SAAgB,EAAU,EAAoB,CAE5C,OADI,OAAO,MAAM,EAAK,QAAQ,CAAC,EAAU,GAClC,EAAU,CAAE,KAAM,EAAK,YAAY,EAAG,MAAO,EAAK,SAAS,EAAI,EAAG,IAAK,EAAK,QAAQ,CAAE,CAAC,CAChG,CAGA,SAAgB,EAAU,EAAmB,CAC3C,IAAM,EAAQ,EAAS,CAAG,EAC1B,GAAI,CAAC,EAAO,OAAO,IAAI,KAAK,GAAG,EAC/B,IAAM,EAAO,IAAI,KAAK,IAAM,EAAG,CAAC,EAEhC,OADA,EAAK,YAAY,EAAM,KAAM,EAAM,MAAQ,EAAG,EAAM,GAAG,EAChD,CACT"}
|
|
1
|
+
{"version":3,"file":"day.mjs","names":[],"sources":["../../../../package/common/utils/day.ts"],"sourcesContent":["// A day is a `'YYYY-MM-DD'` string, the value of `<input type=\"date\">`: no time and no time zone,\n// so it is the same day for everyone. A `Date` is a moment and cannot be one.\n//\n// Dates are built with `setFullYear` rather than the `Date` constructor or `Date.UTC`, which read\n// the years 0 to 99 as 1900 to 1999.\n\nexport interface DayParts {\n year: number;\n /** 1 to 12. */\n month: number;\n day: number;\n}\n\nconst DAY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function daysInMonth({ year, month }: Pick<DayParts, 'year' | 'month'>): number {\n const date = new Date(0);\n date.setUTCFullYear(year, month, 0);\n return date.getUTCDate();\n}\n\n/** The parts of a `'YYYY-MM-DD'` string, or `null` for anything else, 31 February included. */\nexport function parseDay(value: unknown): DayParts | null {\n if (typeof value !== 'string') return null;\n const match = DAY.exec(value);\n if (!match) return null;\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (month < 1 || month > 12 || day < 1 || day > daysInMonth({ year, month })) return null;\n return { year, month, day };\n}\n\n/** `value` itself when it is a `'YYYY-MM-DD'` day that exists, otherwise `null`. */\nexport function asDay(value: unknown): string | null {\n return parseDay(value) ? (value as string) : null;\n}\n\nexport function formatDay({ year, month, day }: DayParts): string {\n return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n}\n\n/** The day `date` falls on in the browser's time zone, as `'YYYY-MM-DD'`; `''` for an Invalid Date. */\nexport function dateToDay(date: Date): string {\n if (Number.isNaN(date.getTime())) return '';\n return formatDay({ year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() });\n}\n\n/** The first moment of a `'YYYY-MM-DD'` day in the browser's time zone. An Invalid Date for anything else. */\nexport function dayToDate(day: string): Date {\n const parts = parseDay(day);\n if (!parts) return new Date(NaN);\n const date = new Date(2000, 0, 1);\n date.setFullYear(parts.year, parts.month - 1, parts.day);\n return date;\n}\n\nconst TIME = /^(\\d{2}):(\\d{2})$/;\n\n/** The `'HH:MM'` of `date` in the browser's time zone, the value a TimeInput holds; `''` for an Invalid Date. */\nexport function dateToTime(date: Date): string {\n if (Number.isNaN(date.getTime())) return '';\n return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;\n}\n\n/**\n * The moment a `'YYYY-MM-DD'` day and an `'HH:MM'` time stand for in the browser's time zone,\n * DatePicker's and TimeInput's values together. A time the clock skips that day resolves forwards\n * (02:30 becomes 03:30), a repeated one to its first occurrence. An Invalid Date for anything else.\n */\nexport function dayTimeToDate(day: string, time: string): Date {\n const date = dayToDate(day);\n const match = TIME.exec(time);\n const hours = match ? Number(match[1]) : NaN;\n const minutes = match ? Number(match[2]) : NaN;\n if (Number.isNaN(date.getTime()) || !(hours <= 23 && minutes <= 59)) return new Date(NaN);\n date.setHours(hours, minutes, 0, 0);\n return date;\n}\n"],"mappings":"aAaA,IAAM,EAAM,4BAEZ,SAAgB,EAAY,CAAE,OAAM,SAAmD,CACrF,IAAM,EAAO,IAAI,KAAK,CAAC,EAEvB,OADA,EAAK,eAAe,EAAM,EAAO,CAAC,EAC3B,EAAK,WAAW,CACzB,CAGA,SAAgB,EAAS,EAAiC,CACxD,GAAI,OAAO,GAAU,SAAU,OAAO,KACtC,IAAM,EAAQ,EAAI,KAAK,CAAK,EAC5B,GAAI,CAAC,EAAO,OAAO,KACnB,IAAM,EAAO,OAAO,EAAM,EAAE,EACtB,EAAQ,OAAO,EAAM,EAAE,EACvB,EAAM,OAAO,EAAM,EAAE,EAE3B,OADI,EAAQ,GAAK,EAAQ,IAAM,EAAM,GAAK,EAAM,EAAY,CAAE,OAAM,OAAM,CAAC,EAAU,KAC9E,CAAE,OAAM,QAAO,KAAI,CAC5B,CAGA,SAAgB,EAAM,EAA+B,CACnD,OAAO,EAAS,CAAK,EAAK,EAAmB,IAC/C,CAEA,SAAgB,EAAU,CAAE,OAAM,QAAO,OAAyB,CAChE,MAAO,GAAG,OAAO,CAAI,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAK,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAG,CAAC,CAAC,SAAS,EAAG,GAAG,GAC1G,CAGA,SAAgB,EAAU,EAAoB,CAE5C,OADI,OAAO,MAAM,EAAK,QAAQ,CAAC,EAAU,GAClC,EAAU,CAAE,KAAM,EAAK,YAAY,EAAG,MAAO,EAAK,SAAS,EAAI,EAAG,IAAK,EAAK,QAAQ,CAAE,CAAC,CAChG,CAGA,SAAgB,EAAU,EAAmB,CAC3C,IAAM,EAAQ,EAAS,CAAG,EAC1B,GAAI,CAAC,EAAO,OAAO,IAAI,KAAK,GAAG,EAC/B,IAAM,EAAO,IAAI,KAAK,IAAM,EAAG,CAAC,EAEhC,OADA,EAAK,YAAY,EAAM,KAAM,EAAM,MAAQ,EAAG,EAAM,GAAG,EAChD,CACT,CAEA,IAAM,EAAO,oBAGb,SAAgB,EAAW,EAAoB,CAE7C,OADI,OAAO,MAAM,EAAK,QAAQ,CAAC,EAAU,GAClC,GAAG,OAAO,EAAK,SAAS,CAAC,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,EAAK,WAAW,CAAC,CAAC,CAAC,SAAS,EAAG,GAAG,GACjG,CAOA,SAAgB,EAAc,EAAa,EAAoB,CAC7D,IAAM,EAAO,EAAU,CAAG,EACpB,EAAQ,EAAK,KAAK,CAAI,EACtB,EAAQ,EAAQ,OAAO,EAAM,EAAE,EAAI,IACnC,EAAU,EAAQ,OAAO,EAAM,EAAE,EAAI,IAG3C,OAFI,OAAO,MAAM,EAAK,QAAQ,CAAC,GAAK,EAAE,GAAS,IAAM,GAAW,IAAY,IAAI,KAAK,GAAG,GACxF,EAAK,SAAS,EAAO,EAAS,EAAG,CAAC,EAC3B,EACT"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{COLUMN_STORAGE_PREFIX as e,buildColumnTemplate as t,buildFrozenTemplate as n,columnWidthVar as r,isColumnInitiallyVisible as i,loadPersistedColumns as a,measureCellWidth as o}from"./virtualList.utils.mjs";import{useCallback as s,useEffect as c,useLayoutEffect as l,useRef as u,useState as d}from"react";function f({columns:f,items:p,multiSelect:m,visibleColumnKeys:h,onVisibleColumnsChange:g,persistColumnsKey:_,showColumnToggle:v,userWidths:y,isFrozen:b,rootRef:x,startIndex:S,endIndex:C,containerHeight:w,containerWidth:T}){let
|
|
1
|
+
"use client";import{COLUMN_STORAGE_PREFIX as e,buildColumnTemplate as t,buildFrozenTemplate as n,columnWidthVar as r,isColumnInitiallyVisible as i,loadPersistedColumns as a,measureCellWidth as o}from"./virtualList.utils.mjs";import{useCallback as s,useEffect as c,useLayoutEffect as l,useRef as u,useState as d}from"react";function f({columns:f,items:p,multiSelect:m,visibleColumnKeys:h,onVisibleColumnsChange:g,persistColumnsKey:_,showColumnToggle:v,userWidths:y,isFrozen:b,rootRef:x,startIndex:S,endIndex:C,containerHeight:w,containerWidth:T,isLoading:E}){let D=h!==void 0,[O,k]=d(!1),[A,j]=d({}),[M,N]=d(()=>{let e=a(_);return new Set((f??[]).filter(t=>i(t,e)).map(e=>e.key))}),P=u(new Set((f??[]).map(e=>e.key)));c(()=>{if(D)return;let e=f??[],t=new Set(e.map(e=>e.key)),n=P.current,r=t.size===n.size;if(r){for(let e of t)if(!n.has(e)){r=!1;break}}if(r)return;P.current=t;let o=a(_);N(t=>{let r=new Set;for(let a of e)n.has(a.key)?t.has(a.key)&&r.add(a.key):i(a,o)&&r.add(a.key);return r})},[f,D,_]),c(()=>{if(D||!_||typeof window>`u`)return;let t=f??[];if(t.length!==0&&M.size!==0)try{window.localStorage.setItem(e+_,JSON.stringify({visible:[...M],known:t.map(e=>e.key),widths:y}))}catch{}},[M,f,D,_,y]);let F=D?new Set(h):M,I=(f??[]).filter(e=>e.lockVisible).map(e=>e.key),L=I.some(e=>!F.has(e))?new Set([...F,...I]):F,R=!!f?.length,z=R?f.filter(e=>L.has(e.key)):[],B=R?f.filter(e=>!e.defaultHidden&&!L.has(e.key)).length:0,V=R?`${m&&R?`40px `:``}${b?n(z):t(z,A)}`:void 0,H=v!==!1&&R&&f.some(e=>!e.hideFromToggle),U={};if(b&&R){let e=z.map(e=>`var(${r(e.key)}, 160px)`);m&&e.unshift(`40px`),H&&e.push(`32px`),U[`--vl-total`]=`calc(${e.join(` + `)})`}let W=z.filter(e=>e.width.type===`fit`),G=!b&&W.length>0,K=W.map(e=>e.key).join(`|`),[q,J]=d({key:K,items:p});(q.key!==K||q.items!==p)&&(J({key:K,items:p}),Object.keys(A).length>0&&j({}));let Y=s(()=>{let e=x.current;if(!e)return;let t=new Map;e.querySelectorAll(`[data-fit-key]`).forEach(e=>{let n=e,r=n.getAttribute(`data-fit-key`);if(!r)return;let i=o(n);i>(t.get(r)??0)&&t.set(r,i)}),t.size!==0&&j(n=>{let r=!1,i={...n};for(let[a,o]of t){if(o<=0)continue;let t=Math.min(Math.ceil(o),e.clientWidth);t>(n[a]??0)&&(i[a]=t,r=!0)}return r?i:n})},[x]),[X]=d(()=>typeof ResizeObserver>`u`?null:new ResizeObserver(()=>Y())),Z=u(new Set);c(()=>()=>{X?.disconnect(),Z.current.clear()},[X]),l(()=>{if(!G)return;let e=x.current;if(!e||(Y(),!X))return;let t=new Set(e.querySelectorAll(`[data-fit-key]`)),n=Z.current;for(let e of n)t.has(e)||(X.unobserve(e),n.delete(e));for(let e of t)n.has(e)||(X.observe(e),n.add(e))},[x,G,K,A,S,C,w,T,p,E,Y,X]),c(()=>{if(!G)return;let e=0,t=requestAnimationFrame(()=>{Y(),e=requestAnimationFrame(()=>Y())});return()=>{cancelAnimationFrame(t),cancelAnimationFrame(e)}},[G,K,p,E,Y]);let Q=s(()=>j({}),[]);function $(e){if(f?.find(t=>t.key===e)?.lockVisible)return;let t=new Set(L);if(t.has(e)){if(t.size<=1)return;t.delete(e)}else t.add(e);let n=[...t];D||N(t),g?.(n)}return{hasColumns:R,visibleColumns:z,columnTemplate:V,widthVars:U,shouldShowToggle:H,effectiveVisible:L,manuallyHiddenCount:B,toggleOpen:O,setToggleOpen:k,handleToggleColumn:$,recalculateColumns:Q}}export{f as useColumns};
|
|
2
2
|
//# sourceMappingURL=useColumns.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useColumns.mjs","names":[],"sources":["../../../../package/common/virtualList/useColumns.ts"],"sourcesContent":["import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\n\nimport {\n buildColumnTemplate,\n buildFrozenTemplate,\n columnWidthVar,\n DEFAULT_FROZEN_WIDTH,\n measureCellWidth,\n loadPersistedColumns,\n isColumnInitiallyVisible,\n COLUMN_STORAGE_PREFIX,\n type PersistedColumns,\n} from './virtualList.utils';\nimport type { VirtualListColumn } from './virtualList.types';\n\ninterface UseColumnsArgs<T> {\n columns?: VirtualListColumn<T>[];\n items: T[];\n multiSelect: boolean;\n visibleColumnKeys?: string[];\n onVisibleColumnsChange?: (keys: string[]) => void;\n persistColumnsKey?: string;\n showColumnToggle?: boolean;\n /** User-set column widths, from `useColumnResize`. */\n userWidths: Record<string, number>;\n /** Whether those widths have taken over the layout. */\n isFrozen: boolean;\n rootRef: React.RefObject<HTMLDivElement | null>;\n /** Visible-window bounds — re-measure `fit` columns as new cells scroll in. */\n startIndex: number;\n endIndex: number;\n containerHeight: number;\n /** Re-measure `fit` columns when the container width settles (e.g. after a route transition). */\n containerWidth: number;\n}\n\nexport interface UseColumnsResult<T> {\n hasColumns: boolean;\n visibleColumns: VirtualListColumn<T>[];\n columnTemplate: string | undefined;\n /**\n * Custom properties for the list element: the total width of a frozen layout,\n * as a `calc()` over the per-column properties so that rewriting one width\n * during a drag updates the total without any bookkeeping.\n */\n widthVars: React.CSSProperties;\n shouldShowToggle: boolean;\n effectiveVisible: Set<string>;\n /** How many default-visible columns the user has hidden (excludes defaultHidden). */\n manuallyHiddenCount: number;\n toggleOpen: boolean;\n setToggleOpen: React.Dispatch<React.SetStateAction<boolean>>;\n handleToggleColumn: (key: string) => void;\n /** Imperative escape hatch: drop fit-column pins so they re-measure on the\n * next layout. For out-of-band content changes that don't flow through a new\n * `items` array or `columns` set (which reset automatically). */\n recalculateColumns: () => void;\n}\n\n/**\n * Table-mode column logic: visibility (controlled or uncontrolled, with\n * localStorage persistence and runtime reconciliation), the toggle popover, and\n * `fit`-column width measurement that pins one shared px track across the header\n * and every row grid so they stay aligned.\n */\nexport function useColumns<T>({\n columns,\n items,\n multiSelect,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n userWidths,\n isFrozen,\n rootRef,\n startIndex,\n endIndex,\n containerHeight,\n containerWidth,\n}: UseColumnsArgs<T>): UseColumnsResult<T> {\n const isControlled = visibleColumnKeys !== undefined;\n const [toggleOpen, setToggleOpen] = useState(false);\n // Measured px widths for `fit` columns, keyed by column key. Pinning these\n // into the shared column template keeps the header and rows aligned (a raw\n // `fit-content` track resolves per-grid and drifts). See the effects below.\n const [fitWidths, setFitWidths] = useState<Record<string, number>>({});\n\n const [internalVisibleKeys, setInternalVisibleKeys] = useState<Set<string>>(() => {\n const persisted = loadPersistedColumns(persistColumnsKey);\n return new Set((columns ?? []).filter((c) => isColumnInitiallyVisible(c, persisted)).map((c) => c.key));\n });\n // The set of column keys the internal visibility state was last reconciled\n // against. The lazy initializer above only runs at mount, so without this a\n // list that mounts in list mode (no columns) and later switches to table mode\n // would keep an empty visible set and render no columns.\n const knownColumnKeysRef = useRef<Set<string>>(new Set((columns ?? []).map((c) => c.key)));\n\n // Re-derive internal visibility when the column set changes at runtime: new\n // columns get their saved/default visibility, removed columns drop out, and\n // existing columns keep whatever the user toggled them to. This is also what\n // applies persisted settings when a list switches from list mode to table\n // mode (columns absent at mount, supplied later).\n useEffect(() => {\n if (isControlled) return;\n const cols = columns ?? [];\n const currentKeys = new Set(cols.map((c) => c.key));\n const known = knownColumnKeysRef.current;\n let identical = currentKeys.size === known.size;\n if (identical)\n for (const k of currentKeys)\n if (!known.has(k)) {\n identical = false;\n break;\n }\n if (identical) return;\n knownColumnKeysRef.current = currentKeys;\n const persisted = loadPersistedColumns(persistColumnsKey);\n setInternalVisibleKeys((prev) => {\n const next = new Set<string>();\n for (const c of cols) {\n if (known.has(c.key)) {\n if (prev.has(c.key)) next.add(c.key); // preserve the current-session choice\n } else if (isColumnInitiallyVisible(c, persisted)) {\n next.add(c.key); // newly-added column: saved setting, else defaultHidden\n }\n }\n return next;\n });\n }, [columns, isControlled, persistColumnsKey]);\n\n // Persist visibility whenever it changes (uncontrolled mode only). Skip while\n // there are no columns, or the transient empty state during a list→table\n // switch before the reconcile effect above has filled in the visible set —\n // writing then would clobber the saved config with an empty set.\n useEffect(() => {\n if (isControlled || !persistColumnsKey || typeof window === 'undefined') return;\n const cols = columns ?? [];\n if (cols.length === 0 || internalVisibleKeys.size === 0) return;\n try {\n window.localStorage.setItem(\n COLUMN_STORAGE_PREFIX + persistColumnsKey,\n JSON.stringify({\n visible: [...internalVisibleKeys],\n known: cols.map((c) => c.key),\n widths: userWidths,\n } satisfies PersistedColumns),\n );\n } catch {\n // Storage full or unavailable — non-fatal, just don't persist.\n }\n }, [internalVisibleKeys, columns, isControlled, persistColumnsKey, userWidths]);\n\n // Locked columns can never be hidden — force them into the visible set even if\n // a controlled `visibleColumnKeys` or persisted state omits them. Only clone\n // (rather than mutate the state Set) when a locked key is actually missing;\n // in uncontrolled mode they're already present via isColumnInitiallyVisible.\n const baseVisible: Set<string> = isControlled ? new Set(visibleColumnKeys) : internalVisibleKeys;\n const lockedKeys = (columns ?? []).filter((c) => c.lockVisible).map((c) => c.key);\n const effectiveVisible: Set<string> = lockedKeys.some((k) => !baseVisible.has(k))\n ? new Set([...baseVisible, ...lockedKeys])\n : baseVisible;\n\n const hasColumns = !!columns?.length;\n const visibleColumns = hasColumns ? columns!.filter((c) => effectiveVisible.has(c.key)) : [];\n // A column counts as \"manually hidden\" only if it's default-visible yet\n // currently hidden — a defaultHidden column being hidden is its default\n // state, not a user choice, so it never contributes to the chip.\n const manuallyHiddenCount = hasColumns\n ? columns!.filter((c) => !c.defaultHidden && !effectiveVisible.has(c.key)).length\n : 0;\n const selectPrefix = multiSelect && hasColumns ? '40px ' : '';\n const columnTemplate = hasColumns\n ? `${selectPrefix}${isFrozen ? buildFrozenTemplate(visibleColumns) : buildColumnTemplate(visibleColumns, fitWidths)}`\n : undefined;\n // Hide the gear entirely when nothing is left to toggle (every column opts out).\n const shouldShowToggle = showColumnToggle !== false && hasColumns && columns!.some((c) => !c.hideFromToggle);\n\n // Sum of the tracks, so the header and body can stretch past the viewport and\n // the list scrolls horizontally instead of clipping. Kept as a `calc()` over\n // the same custom properties the tracks read, so a drag rewriting one of them\n // resizes the row canvas in the same layout pass.\n const widthVars: React.CSSProperties = {};\n if (isFrozen && hasColumns) {\n const parts = visibleColumns.map((c) => `var(${columnWidthVar(c.key)}, ${DEFAULT_FROZEN_WIDTH}px)`);\n if (multiSelect) parts.unshift('40px');\n if (shouldShowToggle) parts.push('32px');\n (widthVars as Record<string, string>)['--vl-total'] = `calc(${parts.join(' + ')})`;\n }\n\n // ── `fit` column width measurement ──────────────────────────────────────────\n const fitColumns = visibleColumns.filter((c) => c.width.type === 'fit');\n // A frozen layout is exact px and ignores the pins, so measuring would only\n // fight the user: `measureFitWidths` never shrinks a column, and every drag\n // narrower than the content would be undone on the next scroll frame.\n const hasFit = !isFrozen && fitColumns.length > 0;\n const fitColKey = fitColumns.map((c) => c.key).join('|');\n\n // Drop the measured pins when the data or the fit-column set changes, so the\n // measure effect below re-reads the true intrinsic width on the next pass —\n // this is what lets a column shrink (during scroll the effect only grows it,\n // to avoid jitter). Resetting state during render is React's recommended\n // pattern for \"reset on prop change\" and avoids a cascading effect render.\n const [fitReset, setFitReset] = useState<{ key: string; items: T[] }>({ key: fitColKey, items });\n if (fitReset.key !== fitColKey || fitReset.items !== items) {\n setFitReset({ key: fitColKey, items });\n if (Object.keys(fitWidths).length > 0) setFitWidths({});\n }\n\n // Measure every fit cell currently in the DOM (header + visible rows), keyed\n // by its `data-fit-key`, and grow each column's pin to the widest. Reading the\n // key off the DOM (rather than closing over `fitColumns`) keeps this a stable\n // callback the ResizeObserver below can reuse. `measureCellWidth` reports the\n // true content width even when the cell is pinned narrower, so a later pass\n // always recovers a column first measured while it was still empty.\n const measureFitWidths = useCallback(() => {\n const root = rootRef.current;\n if (!root) return;\n const maxByKey = new Map<string, number>();\n root.querySelectorAll('[data-fit-key]').forEach((node) => {\n const el = node as HTMLElement;\n const key = el.getAttribute('data-fit-key');\n if (!key) return;\n const w = measureCellWidth(el);\n if (w > (maxByKey.get(key) ?? 0)) maxByKey.set(key, w);\n });\n if (maxByKey.size === 0) return;\n setFitWidths((prev) => {\n let changed = false;\n const next = { ...prev };\n for (const [key, max] of maxByKey) {\n if (max <= 0) continue;\n // Cap at the viewport width so one oversized cell can't blow out layout.\n const pinned = Math.min(Math.ceil(max), root.clientWidth);\n if (pinned > (prev[key] ?? 0)) {\n next[key] = pinned;\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [rootRef]);\n\n // One ResizeObserver shared across all fit cells. It re-measures whenever a\n // cell's box changes — crucially when content first appears after mount (which\n // changes the cell's height even while its width is pinned), so a too-early or\n // empty-cell measure self-corrects instead of sticking. Its initial callback\n // also fires once after layout settles, covering route transitions and other\n // post-mount layout shifts without depending on font/rAF timing.\n const [fitObserver] = useState<ResizeObserver | null>(() =>\n typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => measureFitWidths()),\n );\n const observedRef = useRef<Set<Element>>(new Set());\n useEffect(\n () => () => {\n fitObserver?.disconnect();\n observedRef.current.clear();\n },\n [fitObserver],\n );\n\n // Measure synchronously (before paint, so a wider row scrolling in never shows\n // a clipped frame), then *diff* the observed set rather than re-observing every\n // cell. Re-observing fires a redundant ResizeObserver callback per node, and\n // `startIndex`/`endIndex` change every scroll frame — so observing only the\n // cells that entered (and dropping the ones that left) keeps stable, already\n // pinned cells from generating any observer traffic while scrolling. A newly\n // entered cell still fires exactly once, which is when we want to measure it.\n useLayoutEffect(() => {\n if (!hasFit) return;\n const root = rootRef.current;\n if (!root) return;\n measureFitWidths();\n if (!fitObserver) return;\n const current = new Set<Element>(root.querySelectorAll('[data-fit-key]'));\n const observed = observedRef.current;\n for (const el of observed)\n if (!current.has(el)) {\n fitObserver.unobserve(el);\n observed.delete(el);\n }\n for (const el of current)\n if (!observed.has(el)) {\n fitObserver.observe(el);\n observed.add(el);\n }\n }, [\n rootRef,\n hasFit,\n fitColKey,\n fitWidths,\n startIndex,\n endIndex,\n containerHeight,\n containerWidth,\n items,\n measureFitWidths,\n fitObserver,\n ]);\n\n // Cheap insurance: re-measure on the next two frames after mount / data /\n // fit-column changes, in case the icons (or the injected FontAwesome sizing\n // CSS) resolve a frame after the first synchronous pass. Safe and scoped —\n // measureFitWidths only ever grows a pin, and this runs on mount / data change\n // (not every scroll frame), so it keeps the diff-observe perf win.\n useEffect(() => {\n if (!hasFit) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n measureFitWidths();\n raf2 = requestAnimationFrame(() => measureFitWidths());\n });\n return () => {\n cancelAnimationFrame(raf1);\n cancelAnimationFrame(raf2);\n };\n }, [hasFit, fitColKey, items, measureFitWidths]);\n\n // Force a fresh fit-column measure regardless of current pins. Always installs\n // a new empty object so the measure layout effect re-runs even when nothing\n // was pinned (e.g. content changed while the column was still fit-content).\n const recalculateColumns = useCallback(() => setFitWidths({}), []);\n\n function handleToggleColumn(key: string) {\n // Locked columns can't be toggled off.\n if (columns?.find((c) => c.key === key)?.lockVisible) return;\n const next = new Set(effectiveVisible);\n if (next.has(key)) {\n if (next.size <= 1) return;\n next.delete(key);\n } else {\n next.add(key);\n }\n const nextArray = [...next];\n if (!isControlled) setInternalVisibleKeys(next);\n onVisibleColumnsChange?.(nextArray);\n }\n\n return {\n hasColumns,\n visibleColumns,\n columnTemplate,\n widthVars,\n shouldShowToggle,\n effectiveVisible,\n manuallyHiddenCount,\n toggleOpen,\n setToggleOpen,\n handleToggleColumn,\n recalculateColumns,\n };\n}\n"],"mappings":"mUAiEA,SAAgB,EAAc,CAC5B,UACA,QACA,cACA,oBACA,yBACA,oBACA,mBACA,aACA,WACA,UACA,aACA,WACA,kBACA,kBACyC,CACzC,IAAM,EAAe,IAAsB,IAAA,GACrC,CAAC,EAAY,GAAiB,EAAS,EAAK,EAI5C,CAAC,EAAW,GAAgB,EAAiC,CAAC,CAAC,EAE/D,CAAC,EAAqB,GAA0B,MAA4B,CAChF,IAAM,EAAY,EAAqB,CAAiB,EACxD,OAAO,IAAI,KAAK,GAAW,CAAC,EAAA,CAAG,OAAQ,GAAM,EAAyB,EAAG,CAAS,CAAC,CAAC,CAAC,IAAK,GAAM,EAAE,GAAG,CAAC,CACxG,CAAC,EAKK,EAAqB,EAAoB,IAAI,KAAK,GAAW,CAAC,EAAA,CAAG,IAAK,GAAM,EAAE,GAAG,CAAC,CAAC,EAOzF,MAAgB,CACd,GAAI,EAAc,OAClB,IAAM,EAAO,GAAW,CAAC,EACnB,EAAc,IAAI,IAAI,EAAK,IAAK,GAAM,EAAE,GAAG,CAAC,EAC5C,EAAQ,EAAmB,QAC7B,EAAY,EAAY,OAAS,EAAM,KAC3C,GAAI,EACG,KAAA,IAAM,KAAK,EACd,GAAI,CAAC,EAAM,IAAI,CAAC,EAAG,CACjB,EAAY,GACZ,KACF,EACJ,GAAI,EAAW,OACf,EAAmB,QAAU,EAC7B,IAAM,EAAY,EAAqB,CAAiB,EACxD,EAAwB,GAAS,CAC/B,IAAM,EAAO,IAAI,IACjB,IAAK,IAAM,KAAK,EACV,EAAM,IAAI,EAAE,GAAG,EACb,EAAK,IAAI,EAAE,GAAG,GAAG,EAAK,IAAI,EAAE,GAAG,EAC1B,EAAyB,EAAG,CAAS,GAC9C,EAAK,IAAI,EAAE,GAAG,EAGlB,OAAO,CACT,CAAC,CACH,EAAG,CAAC,EAAS,EAAc,CAAiB,CAAC,EAM7C,MAAgB,CACd,GAAI,GAAgB,CAAC,GAAqB,OAAO,OAAW,IAAa,OACzE,IAAM,EAAO,GAAW,CAAC,EACrB,KAAK,SAAW,GAAK,EAAoB,OAAS,EACtD,GAAI,CACF,OAAO,aAAa,QAClB,EAAwB,EACxB,KAAK,UAAU,CACb,QAAS,CAAC,GAAG,CAAmB,EAChC,MAAO,EAAK,IAAK,GAAM,EAAE,GAAG,EAC5B,OAAQ,CACV,CAA4B,CAC9B,CACF,MAAQ,CAER,CACF,EAAG,CAAC,EAAqB,EAAS,EAAc,EAAmB,CAAU,CAAC,EAM9E,IAAM,EAA2B,EAAe,IAAI,IAAI,CAAiB,EAAI,EACvE,GAAc,GAAW,CAAC,EAAA,CAAG,OAAQ,GAAM,EAAE,WAAW,CAAC,CAAC,IAAK,GAAM,EAAE,GAAG,EAC1E,EAAgC,EAAW,KAAM,GAAM,CAAC,EAAY,IAAI,CAAC,CAAC,EAC5E,IAAI,IAAI,CAAC,GAAG,EAAa,GAAG,CAAU,CAAC,EACvC,EAEE,EAAa,CAAC,CAAC,GAAS,OACxB,EAAiB,EAAa,EAAS,OAAQ,GAAM,EAAiB,IAAI,EAAE,GAAG,CAAC,EAAI,CAAC,EAIrF,EAAsB,EACxB,EAAS,OAAQ,GAAM,CAAC,EAAE,eAAiB,CAAC,EAAiB,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,OACzE,EAEE,EAAiB,EACnB,GAFiB,GAAe,EAAa,QAAU,KAErC,EAAW,EAAoB,CAAc,EAAI,EAAoB,EAAgB,CAAS,IAChH,IAAA,GAEE,EAAmB,IAAqB,IAAS,GAAc,EAAS,KAAM,GAAM,CAAC,EAAE,cAAc,EAMrG,EAAiC,CAAC,EACxC,GAAI,GAAY,EAAY,CAC1B,IAAM,EAAQ,EAAe,IAAK,GAAM,OAAO,EAAe,EAAE,GAAG,EAAE,SAA6B,EAC9F,GAAa,EAAM,QAAQ,MAAM,EACjC,GAAkB,EAAM,KAAK,MAAM,EACvC,EAAsC,cAAgB,QAAQ,EAAM,KAAK,KAAK,EAAE,EAClF,CAGA,IAAM,EAAa,EAAe,OAAQ,GAAM,EAAE,MAAM,OAAS,KAAK,EAIhE,EAAS,CAAC,GAAY,EAAW,OAAS,EAC1C,EAAY,EAAW,IAAK,GAAM,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,EAOjD,CAAC,EAAU,GAAe,EAAsC,CAAE,IAAK,EAAW,OAAM,CAAC,GAC3F,EAAS,MAAQ,GAAa,EAAS,QAAU,KACnD,EAAY,CAAE,IAAK,EAAW,OAAM,CAAC,EACjC,OAAO,KAAK,CAAS,CAAC,CAAC,OAAS,GAAG,EAAa,CAAC,CAAC,GASxD,IAAM,EAAmB,MAAkB,CACzC,IAAM,EAAO,EAAQ,QACrB,GAAI,CAAC,EAAM,OACX,IAAM,EAAW,IAAI,IACrB,EAAK,iBAAiB,gBAAgB,CAAC,CAAC,QAAS,GAAS,CACxD,IAAM,EAAK,EACL,EAAM,EAAG,aAAa,cAAc,EAC1C,GAAI,CAAC,EAAK,OACV,IAAM,EAAI,EAAiB,CAAE,EACzB,GAAK,EAAS,IAAI,CAAG,GAAK,IAAI,EAAS,IAAI,EAAK,CAAC,CACvD,CAAC,EACG,EAAS,OAAS,GACtB,EAAc,GAAS,CACrB,IAAI,EAAU,GACR,EAAO,CAAE,GAAG,CAAK,EACvB,IAAK,GAAM,CAAC,EAAK,KAAQ,EAAU,CACjC,GAAI,GAAO,EAAG,SAEd,IAAM,EAAS,KAAK,IAAI,KAAK,KAAK,CAAG,EAAG,EAAK,WAAW,EACpD,GAAU,EAAK,IAAQ,KACzB,EAAK,GAAO,EACZ,EAAU,GAEd,CACA,OAAO,EAAU,EAAO,CAC1B,CAAC,CACH,EAAG,CAAC,CAAO,CAAC,EAQN,CAAC,GAAe,MACpB,OAAO,eAAmB,IAAc,KAAO,IAAI,mBAAqB,EAAiB,CAAC,CAC5F,EACM,EAAc,EAAqB,IAAI,GAAK,EAClD,UACc,CACV,GAAa,WAAW,EACxB,EAAY,QAAQ,MAAM,CAC5B,EACA,CAAC,CAAW,CACd,EASA,MAAsB,CACpB,GAAI,CAAC,EAAQ,OACb,IAAM,EAAO,EAAQ,QAGrB,GAFI,CAAC,IACL,EAAiB,EACb,CAAC,GAAa,OAClB,IAAM,EAAU,IAAI,IAAa,EAAK,iBAAiB,gBAAgB,CAAC,EAClE,EAAW,EAAY,QAC7B,IAAK,IAAM,KAAM,EACV,EAAQ,IAAI,CAAE,IACjB,EAAY,UAAU,CAAE,EACxB,EAAS,OAAO,CAAE,GAEtB,IAAK,IAAM,KAAM,EACV,EAAS,IAAI,CAAE,IAClB,EAAY,QAAQ,CAAE,EACtB,EAAS,IAAI,CAAE,EAErB,EAAG,CACD,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CACF,CAAC,EAOD,MAAgB,CACd,GAAI,CAAC,EAAQ,OACb,IAAI,EAAO,EACL,EAAO,0BAA4B,CACvC,EAAiB,EACjB,EAAO,0BAA4B,EAAiB,CAAC,CACvD,CAAC,EACD,UAAa,CACX,qBAAqB,CAAI,EACzB,qBAAqB,CAAI,CAC3B,CACF,EAAG,CAAC,EAAQ,EAAW,EAAO,CAAgB,CAAC,EAK/C,IAAM,EAAqB,MAAkB,EAAa,CAAC,CAAC,EAAG,CAAC,CAAC,EAEjE,SAAS,EAAmB,EAAa,CAEvC,GAAI,GAAS,KAAM,GAAM,EAAE,MAAQ,CAAG,CAAC,EAAE,YAAa,OACtD,IAAM,EAAO,IAAI,IAAI,CAAgB,EACrC,GAAI,EAAK,IAAI,CAAG,EAAG,CACjB,GAAI,EAAK,MAAQ,EAAG,OACpB,EAAK,OAAO,CAAG,CACjB,MACE,EAAK,IAAI,CAAG,EAEd,IAAM,EAAY,CAAC,GAAG,CAAI,EACrB,GAAc,EAAuB,CAAI,EAC9C,IAAyB,CAAS,CACpC,CAEA,MAAO,CACL,aACA,iBACA,iBACA,YACA,mBACA,mBACA,sBACA,aACA,gBACA,qBACA,oBACF,CACF"}
|
|
1
|
+
{"version":3,"file":"useColumns.mjs","names":[],"sources":["../../../../package/common/virtualList/useColumns.ts"],"sourcesContent":["import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\n\nimport {\n buildColumnTemplate,\n buildFrozenTemplate,\n columnWidthVar,\n DEFAULT_FROZEN_WIDTH,\n measureCellWidth,\n loadPersistedColumns,\n isColumnInitiallyVisible,\n COLUMN_STORAGE_PREFIX,\n type PersistedColumns,\n} from './virtualList.utils';\nimport type { VirtualListColumn } from './virtualList.types';\n\ninterface UseColumnsArgs<T> {\n columns?: VirtualListColumn<T>[];\n items: T[];\n multiSelect: boolean;\n visibleColumnKeys?: string[];\n onVisibleColumnsChange?: (keys: string[]) => void;\n persistColumnsKey?: string;\n showColumnToggle?: boolean;\n /** User-set column widths, from `useColumnResize`. */\n userWidths: Record<string, number>;\n /** Whether those widths have taken over the layout. */\n isFrozen: boolean;\n rootRef: React.RefObject<HTMLDivElement | null>;\n /** Visible-window bounds — re-measure `fit` columns as new cells scroll in. */\n startIndex: number;\n endIndex: number;\n containerHeight: number;\n /** Re-measure `fit` columns when the container width settles (e.g. after a route transition). */\n containerWidth: number;\n /** Re-measure `fit` columns when rows replace the spinner under the same `items`. */\n isLoading: boolean;\n}\n\nexport interface UseColumnsResult<T> {\n hasColumns: boolean;\n visibleColumns: VirtualListColumn<T>[];\n columnTemplate: string | undefined;\n /**\n * Custom properties for the list element: the total width of a frozen layout,\n * as a `calc()` over the per-column properties so that rewriting one width\n * during a drag updates the total without any bookkeeping.\n */\n widthVars: React.CSSProperties;\n shouldShowToggle: boolean;\n effectiveVisible: Set<string>;\n /** How many default-visible columns the user has hidden (excludes defaultHidden). */\n manuallyHiddenCount: number;\n toggleOpen: boolean;\n setToggleOpen: React.Dispatch<React.SetStateAction<boolean>>;\n handleToggleColumn: (key: string) => void;\n /** Imperative escape hatch: drop fit-column pins so they re-measure on the\n * next layout. For out-of-band content changes that don't flow through a new\n * `items` array or `columns` set (which reset automatically). */\n recalculateColumns: () => void;\n}\n\n/**\n * Table-mode column logic: visibility (controlled or uncontrolled, with\n * localStorage persistence and runtime reconciliation), the toggle popover, and\n * `fit`-column width measurement that pins one shared px track across the header\n * and every row grid so they stay aligned.\n */\nexport function useColumns<T>({\n columns,\n items,\n multiSelect,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n userWidths,\n isFrozen,\n rootRef,\n startIndex,\n endIndex,\n containerHeight,\n containerWidth,\n isLoading,\n}: UseColumnsArgs<T>): UseColumnsResult<T> {\n const isControlled = visibleColumnKeys !== undefined;\n const [toggleOpen, setToggleOpen] = useState(false);\n // Measured px widths for `fit` columns, keyed by column key. Pinning these\n // into the shared column template keeps the header and rows aligned (a raw\n // `fit-content` track resolves per-grid and drifts). See the effects below.\n const [fitWidths, setFitWidths] = useState<Record<string, number>>({});\n\n const [internalVisibleKeys, setInternalVisibleKeys] = useState<Set<string>>(() => {\n const persisted = loadPersistedColumns(persistColumnsKey);\n return new Set((columns ?? []).filter((c) => isColumnInitiallyVisible(c, persisted)).map((c) => c.key));\n });\n // The set of column keys the internal visibility state was last reconciled\n // against. The lazy initializer above only runs at mount, so without this a\n // list that mounts in list mode (no columns) and later switches to table mode\n // would keep an empty visible set and render no columns.\n const knownColumnKeysRef = useRef<Set<string>>(new Set((columns ?? []).map((c) => c.key)));\n\n // Re-derive internal visibility when the column set changes at runtime: new\n // columns get their saved/default visibility, removed columns drop out, and\n // existing columns keep whatever the user toggled them to. This is also what\n // applies persisted settings when a list switches from list mode to table\n // mode (columns absent at mount, supplied later).\n useEffect(() => {\n if (isControlled) return;\n const cols = columns ?? [];\n const currentKeys = new Set(cols.map((c) => c.key));\n const known = knownColumnKeysRef.current;\n let identical = currentKeys.size === known.size;\n if (identical)\n for (const k of currentKeys)\n if (!known.has(k)) {\n identical = false;\n break;\n }\n if (identical) return;\n knownColumnKeysRef.current = currentKeys;\n const persisted = loadPersistedColumns(persistColumnsKey);\n setInternalVisibleKeys((prev) => {\n const next = new Set<string>();\n for (const c of cols) {\n if (known.has(c.key)) {\n if (prev.has(c.key)) next.add(c.key); // preserve the current-session choice\n } else if (isColumnInitiallyVisible(c, persisted)) {\n next.add(c.key); // newly-added column: saved setting, else defaultHidden\n }\n }\n return next;\n });\n }, [columns, isControlled, persistColumnsKey]);\n\n // Persist visibility whenever it changes (uncontrolled mode only). Skip while\n // there are no columns, or the transient empty state during a list→table\n // switch before the reconcile effect above has filled in the visible set —\n // writing then would clobber the saved config with an empty set.\n useEffect(() => {\n if (isControlled || !persistColumnsKey || typeof window === 'undefined') return;\n const cols = columns ?? [];\n if (cols.length === 0 || internalVisibleKeys.size === 0) return;\n try {\n window.localStorage.setItem(\n COLUMN_STORAGE_PREFIX + persistColumnsKey,\n JSON.stringify({\n visible: [...internalVisibleKeys],\n known: cols.map((c) => c.key),\n widths: userWidths,\n } satisfies PersistedColumns),\n );\n } catch {\n // Storage full or unavailable — non-fatal, just don't persist.\n }\n }, [internalVisibleKeys, columns, isControlled, persistColumnsKey, userWidths]);\n\n // Locked columns can never be hidden — force them into the visible set even if\n // a controlled `visibleColumnKeys` or persisted state omits them. Only clone\n // (rather than mutate the state Set) when a locked key is actually missing;\n // in uncontrolled mode they're already present via isColumnInitiallyVisible.\n const baseVisible: Set<string> = isControlled ? new Set(visibleColumnKeys) : internalVisibleKeys;\n const lockedKeys = (columns ?? []).filter((c) => c.lockVisible).map((c) => c.key);\n const effectiveVisible: Set<string> = lockedKeys.some((k) => !baseVisible.has(k))\n ? new Set([...baseVisible, ...lockedKeys])\n : baseVisible;\n\n const hasColumns = !!columns?.length;\n const visibleColumns = hasColumns ? columns!.filter((c) => effectiveVisible.has(c.key)) : [];\n // A column counts as \"manually hidden\" only if it's default-visible yet\n // currently hidden — a defaultHidden column being hidden is its default\n // state, not a user choice, so it never contributes to the chip.\n const manuallyHiddenCount = hasColumns\n ? columns!.filter((c) => !c.defaultHidden && !effectiveVisible.has(c.key)).length\n : 0;\n const selectPrefix = multiSelect && hasColumns ? '40px ' : '';\n const columnTemplate = hasColumns\n ? `${selectPrefix}${isFrozen ? buildFrozenTemplate(visibleColumns) : buildColumnTemplate(visibleColumns, fitWidths)}`\n : undefined;\n // Hide the gear entirely when nothing is left to toggle (every column opts out).\n const shouldShowToggle = showColumnToggle !== false && hasColumns && columns!.some((c) => !c.hideFromToggle);\n\n // Sum of the tracks, so the header and body can stretch past the viewport and\n // the list scrolls horizontally instead of clipping. Kept as a `calc()` over\n // the same custom properties the tracks read, so a drag rewriting one of them\n // resizes the row canvas in the same layout pass.\n const widthVars: React.CSSProperties = {};\n if (isFrozen && hasColumns) {\n const parts = visibleColumns.map((c) => `var(${columnWidthVar(c.key)}, ${DEFAULT_FROZEN_WIDTH}px)`);\n if (multiSelect) parts.unshift('40px');\n if (shouldShowToggle) parts.push('32px');\n (widthVars as Record<string, string>)['--vl-total'] = `calc(${parts.join(' + ')})`;\n }\n\n // ── `fit` column width measurement ──────────────────────────────────────────\n const fitColumns = visibleColumns.filter((c) => c.width.type === 'fit');\n // A frozen layout is exact px and ignores the pins, so measuring would only\n // fight the user: `measureFitWidths` never shrinks a column, and every drag\n // narrower than the content would be undone on the next scroll frame.\n const hasFit = !isFrozen && fitColumns.length > 0;\n const fitColKey = fitColumns.map((c) => c.key).join('|');\n\n // Drop the measured pins when the data or the fit-column set changes, so the\n // measure effect below re-reads the true intrinsic width on the next pass —\n // this is what lets a column shrink (during scroll the effect only grows it,\n // to avoid jitter). Resetting state during render is React's recommended\n // pattern for \"reset on prop change\" and avoids a cascading effect render.\n const [fitReset, setFitReset] = useState<{ key: string; items: T[] }>({ key: fitColKey, items });\n if (fitReset.key !== fitColKey || fitReset.items !== items) {\n setFitReset({ key: fitColKey, items });\n if (Object.keys(fitWidths).length > 0) setFitWidths({});\n }\n\n // Measure every fit cell currently in the DOM (header + visible rows), keyed\n // by its `data-fit-key`, and grow each column's pin to the widest. Reading the\n // key off the DOM (rather than closing over `fitColumns`) keeps this a stable\n // callback the ResizeObserver below can reuse. `measureCellWidth` reports the\n // true content width even when the cell is pinned narrower, so a later pass\n // always recovers a column first measured while it was still empty.\n const measureFitWidths = useCallback(() => {\n const root = rootRef.current;\n if (!root) return;\n const maxByKey = new Map<string, number>();\n root.querySelectorAll('[data-fit-key]').forEach((node) => {\n const el = node as HTMLElement;\n const key = el.getAttribute('data-fit-key');\n if (!key) return;\n const w = measureCellWidth(el);\n if (w > (maxByKey.get(key) ?? 0)) maxByKey.set(key, w);\n });\n if (maxByKey.size === 0) return;\n setFitWidths((prev) => {\n let changed = false;\n const next = { ...prev };\n for (const [key, max] of maxByKey) {\n if (max <= 0) continue;\n // Cap at the viewport width so one oversized cell can't blow out layout.\n const pinned = Math.min(Math.ceil(max), root.clientWidth);\n if (pinned > (prev[key] ?? 0)) {\n next[key] = pinned;\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [rootRef]);\n\n // One ResizeObserver shared across all fit cells. It re-measures whenever a\n // cell's box changes — crucially when content first appears after mount (which\n // changes the cell's height even while its width is pinned), so a too-early or\n // empty-cell measure self-corrects instead of sticking. Its initial callback\n // also fires once after layout settles, covering route transitions and other\n // post-mount layout shifts without depending on font/rAF timing.\n const [fitObserver] = useState<ResizeObserver | null>(() =>\n typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => measureFitWidths()),\n );\n const observedRef = useRef<Set<Element>>(new Set());\n useEffect(\n () => () => {\n fitObserver?.disconnect();\n observedRef.current.clear();\n },\n [fitObserver],\n );\n\n // Measure synchronously (before paint, so a wider row scrolling in never shows\n // a clipped frame), then *diff* the observed set rather than re-observing every\n // cell. Re-observing fires a redundant ResizeObserver callback per node, and\n // `startIndex`/`endIndex` change every scroll frame — so observing only the\n // cells that entered (and dropping the ones that left) keeps stable, already\n // pinned cells from generating any observer traffic while scrolling. A newly\n // entered cell still fires exactly once, which is when we want to measure it.\n useLayoutEffect(() => {\n if (!hasFit) return;\n const root = rootRef.current;\n if (!root) return;\n measureFitWidths();\n if (!fitObserver) return;\n const current = new Set<Element>(root.querySelectorAll('[data-fit-key]'));\n const observed = observedRef.current;\n for (const el of observed)\n if (!current.has(el)) {\n fitObserver.unobserve(el);\n observed.delete(el);\n }\n for (const el of current)\n if (!observed.has(el)) {\n fitObserver.observe(el);\n observed.add(el);\n }\n }, [\n rootRef,\n hasFit,\n fitColKey,\n fitWidths,\n startIndex,\n endIndex,\n containerHeight,\n containerWidth,\n items,\n isLoading,\n measureFitWidths,\n fitObserver,\n ]);\n\n // Cheap insurance: re-measure on the next two frames after mount / data /\n // fit-column changes, in case the icons (or the injected FontAwesome sizing\n // CSS) resolve a frame after the first synchronous pass. Safe and scoped —\n // measureFitWidths only ever grows a pin, and this runs on mount / data change\n // (not every scroll frame), so it keeps the diff-observe perf win.\n useEffect(() => {\n if (!hasFit) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n measureFitWidths();\n raf2 = requestAnimationFrame(() => measureFitWidths());\n });\n return () => {\n cancelAnimationFrame(raf1);\n cancelAnimationFrame(raf2);\n };\n }, [hasFit, fitColKey, items, isLoading, measureFitWidths]);\n\n // Force a fresh fit-column measure regardless of current pins. Always installs\n // a new empty object so the measure layout effect re-runs even when nothing\n // was pinned (e.g. content changed while the column was still fit-content).\n const recalculateColumns = useCallback(() => setFitWidths({}), []);\n\n function handleToggleColumn(key: string) {\n // Locked columns can't be toggled off.\n if (columns?.find((c) => c.key === key)?.lockVisible) return;\n const next = new Set(effectiveVisible);\n if (next.has(key)) {\n if (next.size <= 1) return;\n next.delete(key);\n } else {\n next.add(key);\n }\n const nextArray = [...next];\n if (!isControlled) setInternalVisibleKeys(next);\n onVisibleColumnsChange?.(nextArray);\n }\n\n return {\n hasColumns,\n visibleColumns,\n columnTemplate,\n widthVars,\n shouldShowToggle,\n effectiveVisible,\n manuallyHiddenCount,\n toggleOpen,\n setToggleOpen,\n handleToggleColumn,\n recalculateColumns,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{useLabels as e}from"../configProvider/useLabels.mjs";import t from"../loading/spinnerLoading/index.mjs";import n from"../checkbox/checkbox.mjs";import r from"./virtualList.module.mjs";import"./virtualList.utils.mjs";import ee from"./virtualRow.mjs";import i from"./virtualListHeader.mjs";import{useVirtualWindow as a}from"./useVirtualWindow.mjs";import{useSelection as o}from"./useSelection.mjs";import{useColumns as te}from"./useColumns.mjs";import{useRowDrag as ne}from"./useRowDrag.mjs";import{useSorting as re}from"./useSorting.mjs";import{useColumnResize as ie}from"./useColumnResize.mjs";import{useRowNavigation as ae}from"./useRowNavigation.mjs";import{useCallback as oe,useEffect as s,useId as se,useImperativeHandle as ce,useMemo as c,useRef as le}from"react";import l from"classnames";import{Fragment as ue,jsx as u,jsxs as d}from"react/jsx-runtime";var de={selectRow:`Select row`,selectAllRows:`Select all rows`,toggleColumns:`Toggle column visibility`,columnsHidden:e=>`${e} columns hidden`,resetColumnWidths:`Reset column widths`};function f(e,t){return!e||!t?e??t:n=>{e(n),t(n)}}function p(p){let{ref:fe,items:pe,renderRow:me,ariaRoles:m,columns:h,height:he=`100%`,estimatedRowHeight:ge=40,overscan:_e=3,rowGap:ve=0,rowPadding:g,selectedKey:_,getItemKey:v,onRowClick:y,keyboardNavigation:b=!0,tabAcrossRows:ye=!1,scrollParent:be,visibleColumnKeys:xe,onVisibleColumnsChange:Se,persistColumnsKey:x,resizableColumns:Ce=!1,columnWidths:we,onColumnWidthsChange:Te,labels:Ee,sort:De,defaultSort:Oe,onSortChange:ke,showColumnToggle:Ae,onLoadMore:je,loadMoreThreshold:Me=100,isLoading:S=!1,multiSelect:C=!1,selectedKeys:Ne,onSelectionChange:Pe,reorderable:w=!1,onReorder:Fe,longPressDelay:Ie=400,treeReorder:T=!1,getItemDepth:E,isGroup:D,onTreeDrop:Le,treeIndentPx:Re=24,dragHandle:ze=!1,showDivider:Be=!0,rowHover:Ve=!0,className:He,style:Ue,classNames:O,styles:k,...A}=p,j=p.scrollParent!=null&&p.height!==void 0;s(()=>{j&&console.warn("VirtualList: `height` is ignored alongside `scrollParent`, which leaves the list no viewport to size.")},[j]);let M=e(`VirtualList`,Ee,de),{rows:N,effectiveSort:We,isSorted:P,handleHeaderSort:Ge}=re({items:pe,columns:h,sort:De,defaultSort:Oe,onSortChange:ke}),F=oe((e,t)=>v?v(e,t):t,[v]),I=c(()=>N.map((e,t)=>F(e,t)),[N,F]),Ke=c(()=>E?N.map((e,t)=>E(e,t)):[],[N,E]),qe=oe(e=>D?D(N[e],e):!1,[D,N]),L=a({items:N,keys:I,getItemKey:v,estimatedRowHeight:ge,rowGap:ve,overscan:_e,onLoadMore:je,loadMoreThreshold:Me,isLoading:S,scrollParent:be}),{rootRef:R,headerRef:z,rowObserver:Je,keysRef:Ye,offsets:B,totalHeight:Xe,startIndex:V,endIndex:H}=L,U=le([]),W=ie({columns:h,visibleColumnsRef:U,resizableColumns:Ce,columnWidths:we,onColumnWidthsChange:Te,persistColumnsKey:x,rootRef:R}),G=o({items:N,getKey:F,multiSelect:C,selectedKeys:Ne,onSelectionChange:Pe}),{effectiveSelectedKeys:K}=G,q=te({columns:h,items:N,multiSelect:C,visibleColumnKeys:xe,onVisibleColumnsChange:Se,persistColumnsKey:x,showColumnToggle:Ae,userWidths:W.widths,isFrozen:W.isFrozen,rootRef:R,startIndex:V,endIndex:H,containerHeight:L.containerHeight,containerWidth:L.containerWidth}),{hasColumns:J,visibleColumns:Ze,columnTemplate:Qe,widthVars:$e,shouldShowToggle:et,recalculateColumns:tt}=q;U.current=Ze,ce(fe,()=>({...L.scrollApi,recalculateColumns:tt,resetColumnWidths:W.reset}),[L.scrollApi,tt,W.reset]);let nt=P&&(w||T);s(()=>{nt&&console.warn(`VirtualList: row reordering is disabled while the list is sorted. Clear the sort to drag rows.`)},[nt]);let Y=ne({reorderable:w&&!P,treeReorder:T&&!P,onReorder:Fe,onTreeDrop:Le,longPressDelay:Ie,dragHandle:ze,treeIndentPx:Re,keys:I,depths:Ke,isGroupAt:qe,rootRef:R,keysRef:Ye,getVisibleRect:L.getVisibleRect,scrollBy:L.scrollBy}),rt=se(),it=e=>`${rt}-row-${e}`,X=ae({enabled:b,tabAcrossRows:ye,rowCount:N.length,offsets:B,rootRef:R,headerRef:z,getVisibleSlice:L.getVisibleSlice,viewportHeight:L.viewportHeight,scrollToIndex:L.scrollApi.scrollToIndex,initialIndex:_==null?0:Math.max(0,I.indexOf(_)),multiSelect:C,onActivate:y&&(e=>y(N[e],e)),onToggleSelect:e=>G.handleRowSelect(I[e])}),at=typeof g==`number`?`${g}px`:g,Z=e=>{let t=N[e],i=F(t,e),a=_!=null&&i===_||K.has(i),o=Y.getRowDragProps(e,i);return u(ee,{id:it(e),index:e,top:B[e],padding:at,columnTemplate:Qe,isSelected:a,isActive:e===X.activeIndex,manageTabStops:b,isEntered:e===X.enteredIndex,activeClassName:O?.activeRow,activeStyle:k?.activeRow,showDivider:Be,hover:Ve,onClick:()=>{Y.consumeSuppressedClick()||(X.setActiveIndex(e),y?.(t,e))},observer:Je,ariaRowIndex:J?e+2:void 0,ariaPosInSet:J?void 0:e+1,ariaSetSize:J?void 0:N.length,rowRole:m?.row??(J?`row`:`listitem`),reserveToggleGutter:et,...o,dropIndicatorClassName:O?.dropIndicator,dropIndicatorStyle:k?.dropIndicator,rowClassName:O?.row,rowStyle:k?.row,children:J?d(ue,{children:[C&&u(`div`,{className:l(r.virtualListSelectCell,O?.selectCell),style:k?.selectCell,role:`gridcell`,onClick:e=>e.stopPropagation(),children:u(n,{selected:K.has(i),onToggle:()=>G.handleRowSelect(i),"aria-label":M.selectRow,tabIndex:-1})}),Ze.map(n=>u(`div`,{className:l(r.virtualListCell,O?.cell),style:k?.cell,role:`gridcell`,"data-col-key":n.key,"data-fit-key":n.width.type===`fit`?n.key:void 0,children:n.renderCell(t,e)},n.key))]}):me?.(t,e)},i)},Q=[];for(let e=V;e<=H;e++)Q.push(Z(e));let $=Y.draggingKey==null?-1:I.indexOf(Y.draggingKey);$>=0&&($<V||$>H)&&Q.push(Z($)),X.enteredIndex>=0&&(X.enteredIndex<V||X.enteredIndex>H)&&Q.push(Z(X.enteredIndex));let ot={...X.containerProps,onKeyDown:f(A.onKeyDown,X.containerProps.onKeyDown),onFocus:f(A.onFocus,X.containerProps.onFocus),onBlur:f(A.onBlur,X.containerProps.onBlur)};return d(`div`,{...A,...ot,ref:R,className:l(r.virtualList,L.isWindowed&&r.virtualListWindowed,Y.draggingKey!=null&&r.virtualListReordering,W.isResizing&&r.virtualListResizing,He,O?.root),style:{...L.isWindowed?null:{height:he},...$e,...Ue,...k?.root},role:m?.container??(J?`grid`:`list`),"aria-rowcount":J?N.length+1:void 0,"aria-activedescendant":X.activeIndex>=0&&(m?.container??(J?`grid`:`list`))!==`list`?it(X.activeIndex):void 0,children:[J&&u(i,{headerRef:z,columns:h,cols:q,resize:W,sort:We,onSort:Ge,multiSelect:C,allSelected:G.allSelected,someSelected:G.someSelected,onSelectAll:G.handleSelectAll,labels:M,classNames:O,styles:k}),S?u(`div`,{className:r.virtualListLoadingFull,children:u(t,{className:r.virtualListSpinner})}):u(`div`,{className:l(r.virtualListBody,O?.body),style:{height:Xe,...k?.body},children:Q}),L.showLoadMoreSpinner&&u(`div`,{className:l(r.virtualListLoadingIndicator,O?.loadingIndicator),style:k?.loadingIndicator,children:u(t,{className:r.virtualListSpinner})})]})}export{p as default};
|
|
1
|
+
"use client";import{useLabels as e}from"../configProvider/useLabels.mjs";import t from"../loading/spinnerLoading/index.mjs";import n from"../checkbox/checkbox.mjs";import r from"./virtualList.module.mjs";import"./virtualList.utils.mjs";import ee from"./virtualRow.mjs";import i from"./virtualListHeader.mjs";import{useVirtualWindow as a}from"./useVirtualWindow.mjs";import{useSelection as o}from"./useSelection.mjs";import{useColumns as te}from"./useColumns.mjs";import{useRowDrag as ne}from"./useRowDrag.mjs";import{useSorting as re}from"./useSorting.mjs";import{useColumnResize as ie}from"./useColumnResize.mjs";import{useRowNavigation as ae}from"./useRowNavigation.mjs";import{useCallback as oe,useEffect as s,useId as se,useImperativeHandle as ce,useMemo as c,useRef as le}from"react";import l from"classnames";import{Fragment as ue,jsx as u,jsxs as d}from"react/jsx-runtime";var de={selectRow:`Select row`,selectAllRows:`Select all rows`,toggleColumns:`Toggle column visibility`,columnsHidden:e=>`${e} columns hidden`,resetColumnWidths:`Reset column widths`};function f(e,t){return!e||!t?e??t:n=>{e(n),t(n)}}function p(p){let{ref:fe,items:pe,renderRow:me,ariaRoles:m,columns:h,height:he=`100%`,estimatedRowHeight:ge=40,overscan:_e=3,rowGap:ve=0,rowPadding:g,selectedKey:_,getItemKey:v,onRowClick:y,keyboardNavigation:b=!0,tabAcrossRows:ye=!1,scrollParent:be,visibleColumnKeys:xe,onVisibleColumnsChange:Se,persistColumnsKey:x,resizableColumns:Ce=!1,columnWidths:we,onColumnWidthsChange:Te,labels:Ee,sort:De,defaultSort:Oe,onSortChange:ke,showColumnToggle:Ae,onLoadMore:je,loadMoreThreshold:Me=100,isLoading:S=!1,multiSelect:C=!1,selectedKeys:Ne,onSelectionChange:Pe,reorderable:w=!1,onReorder:Fe,longPressDelay:Ie=400,treeReorder:T=!1,getItemDepth:E,isGroup:D,onTreeDrop:Le,treeIndentPx:Re=24,dragHandle:ze=!1,showDivider:Be=!0,rowHover:Ve=!0,className:He,style:Ue,classNames:O,styles:k,...A}=p,j=p.scrollParent!=null&&p.height!==void 0;s(()=>{j&&console.warn("VirtualList: `height` is ignored alongside `scrollParent`, which leaves the list no viewport to size.")},[j]);let M=e(`VirtualList`,Ee,de),{rows:N,effectiveSort:We,isSorted:P,handleHeaderSort:Ge}=re({items:pe,columns:h,sort:De,defaultSort:Oe,onSortChange:ke}),F=oe((e,t)=>v?v(e,t):t,[v]),I=c(()=>N.map((e,t)=>F(e,t)),[N,F]),Ke=c(()=>E?N.map((e,t)=>E(e,t)):[],[N,E]),qe=oe(e=>D?D(N[e],e):!1,[D,N]),L=a({items:N,keys:I,getItemKey:v,estimatedRowHeight:ge,rowGap:ve,overscan:_e,onLoadMore:je,loadMoreThreshold:Me,isLoading:S,scrollParent:be}),{rootRef:R,headerRef:z,rowObserver:Je,keysRef:Ye,offsets:B,totalHeight:Xe,startIndex:V,endIndex:H}=L,U=le([]),W=ie({columns:h,visibleColumnsRef:U,resizableColumns:Ce,columnWidths:we,onColumnWidthsChange:Te,persistColumnsKey:x,rootRef:R}),G=o({items:N,getKey:F,multiSelect:C,selectedKeys:Ne,onSelectionChange:Pe}),{effectiveSelectedKeys:K}=G,q=te({columns:h,items:N,multiSelect:C,visibleColumnKeys:xe,onVisibleColumnsChange:Se,persistColumnsKey:x,showColumnToggle:Ae,userWidths:W.widths,isFrozen:W.isFrozen,rootRef:R,startIndex:V,endIndex:H,containerHeight:L.containerHeight,containerWidth:L.containerWidth,isLoading:S}),{hasColumns:J,visibleColumns:Ze,columnTemplate:Qe,widthVars:$e,shouldShowToggle:et,recalculateColumns:tt}=q;U.current=Ze,ce(fe,()=>({...L.scrollApi,recalculateColumns:tt,resetColumnWidths:W.reset}),[L.scrollApi,tt,W.reset]);let nt=P&&(w||T);s(()=>{nt&&console.warn(`VirtualList: row reordering is disabled while the list is sorted. Clear the sort to drag rows.`)},[nt]);let Y=ne({reorderable:w&&!P,treeReorder:T&&!P,onReorder:Fe,onTreeDrop:Le,longPressDelay:Ie,dragHandle:ze,treeIndentPx:Re,keys:I,depths:Ke,isGroupAt:qe,rootRef:R,keysRef:Ye,getVisibleRect:L.getVisibleRect,scrollBy:L.scrollBy}),rt=se(),it=e=>`${rt}-row-${e}`,X=ae({enabled:b,tabAcrossRows:ye,rowCount:N.length,offsets:B,rootRef:R,headerRef:z,getVisibleSlice:L.getVisibleSlice,viewportHeight:L.viewportHeight,scrollToIndex:L.scrollApi.scrollToIndex,initialIndex:_==null?0:Math.max(0,I.indexOf(_)),multiSelect:C,onActivate:y&&(e=>y(N[e],e)),onToggleSelect:e=>G.handleRowSelect(I[e])}),at=typeof g==`number`?`${g}px`:g,Z=e=>{let t=N[e],i=F(t,e),a=_!=null&&i===_||K.has(i),o=Y.getRowDragProps(e,i);return u(ee,{id:it(e),index:e,top:B[e],padding:at,columnTemplate:Qe,isSelected:a,isActive:e===X.activeIndex,manageTabStops:b,isEntered:e===X.enteredIndex,activeClassName:O?.activeRow,activeStyle:k?.activeRow,showDivider:Be,hover:Ve,onClick:()=>{Y.consumeSuppressedClick()||(X.setActiveIndex(e),y?.(t,e))},observer:Je,ariaRowIndex:J?e+2:void 0,ariaPosInSet:J?void 0:e+1,ariaSetSize:J?void 0:N.length,rowRole:m?.row??(J?`row`:`listitem`),reserveToggleGutter:et,...o,dropIndicatorClassName:O?.dropIndicator,dropIndicatorStyle:k?.dropIndicator,rowClassName:O?.row,rowStyle:k?.row,children:J?d(ue,{children:[C&&u(`div`,{className:l(r.virtualListSelectCell,O?.selectCell),style:k?.selectCell,role:`gridcell`,onClick:e=>e.stopPropagation(),children:u(n,{selected:K.has(i),onToggle:()=>G.handleRowSelect(i),"aria-label":M.selectRow,tabIndex:-1})}),Ze.map(n=>u(`div`,{className:l(r.virtualListCell,O?.cell),style:k?.cell,role:`gridcell`,"data-col-key":n.key,"data-fit-key":n.width.type===`fit`?n.key:void 0,children:n.renderCell(t,e)},n.key))]}):me?.(t,e)},i)},Q=[];for(let e=V;e<=H;e++)Q.push(Z(e));let $=Y.draggingKey==null?-1:I.indexOf(Y.draggingKey);$>=0&&($<V||$>H)&&Q.push(Z($)),X.enteredIndex>=0&&(X.enteredIndex<V||X.enteredIndex>H)&&Q.push(Z(X.enteredIndex));let ot={...X.containerProps,onKeyDown:f(A.onKeyDown,X.containerProps.onKeyDown),onFocus:f(A.onFocus,X.containerProps.onFocus),onBlur:f(A.onBlur,X.containerProps.onBlur)};return d(`div`,{...A,...ot,ref:R,className:l(r.virtualList,L.isWindowed&&r.virtualListWindowed,Y.draggingKey!=null&&r.virtualListReordering,W.isResizing&&r.virtualListResizing,He,O?.root),style:{...L.isWindowed?null:{height:he},...$e,...Ue,...k?.root},role:m?.container??(J?`grid`:`list`),"aria-rowcount":J?N.length+1:void 0,"aria-activedescendant":X.activeIndex>=0&&(m?.container??(J?`grid`:`list`))!==`list`?it(X.activeIndex):void 0,children:[J&&u(i,{headerRef:z,columns:h,cols:q,resize:W,sort:We,onSort:Ge,multiSelect:C,allSelected:G.allSelected,someSelected:G.someSelected,onSelectAll:G.handleSelectAll,labels:M,classNames:O,styles:k}),S?u(`div`,{className:r.virtualListLoadingFull,children:u(t,{className:r.virtualListSpinner})}):u(`div`,{className:l(r.virtualListBody,O?.body),style:{height:Xe,...k?.body},children:Q}),L.showLoadMoreSpinner&&u(`div`,{className:l(r.virtualListLoadingIndicator,O?.loadingIndicator),style:k?.loadingIndicator,children:u(t,{className:r.virtualListSpinner})})]})}export{p 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, useEffect, useId, useImperativeHandle, useRef } from 'react';\nimport cx from 'classnames';\nimport styles from './virtualList.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport Checkbox from '../checkbox';\nimport VirtualRow from './virtualRow';\nimport VirtualListHeader from './virtualListHeader';\nimport { useVirtualWindow } from './useVirtualWindow';\nimport { useSelection } from './useSelection';\nimport { useColumns } from './useColumns';\nimport { useRowDrag } from './useRowDrag';\nimport { useSorting } from './useSorting';\nimport { useColumnResize } from './useColumnResize';\nimport { useRowNavigation } from './useRowNavigation';\nimport { useLabels } from '../configProvider';\nimport type { VirtualListColumn, VirtualListLabels, VirtualListProps } from './virtualList.types';\n\nconst DEFAULT_LABELS: Required<VirtualListLabels> = {\n selectRow: 'Select row',\n selectAllRows: 'Select all rows',\n toggleColumns: 'Toggle column visibility',\n columnsHidden: (count) => `${count} columns hidden`,\n resetColumnWidths: 'Reset column widths',\n};\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 compareSortValues,\n isColumnSortable,\n isEmptySortValue,\n nextSort,\n sortItems,\n} from './virtualList.utils';\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n// VirtualListInner wires the hooks together and renders the two pieces of\n// markup. Each concern lives in its own module:\n// useSorting — table mode: header sort state, and the sorted row order\n// useVirtualWindow — generic scroll / measurement / windowing (all modes)\n// useColumnResize — table mode: user column widths, and the drag that sets them\n// useSelection — multi-row selection\n// useColumns — table mode: columns, visibility, persistence, fit widths\n// useRowDrag — reorder + tree drag-and-drop (mouse + touch)\n// useRowNavigation — arrow-key navigation over the rows\n// virtualListHeader — the header row: sorting, resizing, the column menu\n// virtualRow — one positioned row, with its drag wiring\n//\n// The hook order is not free: useColumnResize decides whether the layout is\n// frozen, which useColumns needs to build the grid template.\n\n/** One handler after the other, or whichever of the two exists. */\nfunction chain<E>(theirs: ((event: E) => void) | undefined, ours: ((event: E) => void) | undefined) {\n if (!theirs || !ours) return theirs ?? ours;\n return (event: E) => {\n theirs(event);\n ours(event);\n };\n}\n\nfunction VirtualList<T>(props: VirtualListProps<T>) {\n const {\n ref,\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 keyboardNavigation = true,\n tabAcrossRows = false,\n scrollParent,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n resizableColumns = false,\n columnWidths,\n onColumnWidthsChange,\n labels,\n sort,\n defaultSort,\n onSortChange,\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 } = props;\n // Read off the raw props: the destructured value carries a default and so\n // cannot tell a passed '100%' from an omitted one.\n const heightIgnored = props.scrollParent != null && props.height !== undefined;\n useEffect(() => {\n if (heightIgnored)\n console.warn(\n 'VirtualList: `height` is ignored alongside `scrollParent`, which leaves the list no viewport to size.',\n );\n }, [heightIgnored]);\n\n const text = useLabels('VirtualList', labels, DEFAULT_LABELS);\n const { rows, effectiveSort, isSorted, handleHeaderSort } = useSorting<T>({\n items,\n columns,\n sort,\n defaultSort,\n onSortChange,\n });\n\n const getKey = useCallback(\n (item: T, index: number): string | number => (getItemKey ? getItemKey(item, index) : index),\n [getItemKey],\n );\n const keys = useMemo(() => rows.map((item, i) => getKey(item, i)), [rows, getKey]);\n const depths = useMemo(\n () => (getItemDepth ? rows.map((item, i) => getItemDepth(item, i)) : []),\n [rows, getItemDepth],\n );\n const isGroupAt = useCallback((i: number) => (isGroup ? isGroup(rows[i], i) : false), [isGroup, rows]);\n\n const win = useVirtualWindow<T>({\n items: rows,\n keys,\n getItemKey,\n estimatedRowHeight,\n rowGap,\n overscan,\n onLoadMore,\n loadMoreThreshold,\n isLoading,\n scrollParent,\n });\n const { rootRef, headerRef, rowObserver, keysRef, offsets, totalHeight, startIndex, endIndex } = win;\n\n // Filled from `cols` below: the resize hook only reads the visible set when a\n // handle is actually used, which is what lets it run before the hook that\n // derives it.\n const visibleColumnsRef = useRef<VirtualListColumn<T>[]>([]);\n const columnResize = useColumnResize<T>({\n columns,\n visibleColumnsRef,\n resizableColumns,\n columnWidths,\n onColumnWidthsChange,\n persistColumnsKey,\n rootRef,\n });\n\n const selection = useSelection<T>({ items: rows, getKey, multiSelect, selectedKeys, onSelectionChange });\n const { effectiveSelectedKeys } = selection;\n\n const cols = useColumns<T>({\n columns,\n items: rows,\n multiSelect,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n userWidths: columnResize.widths,\n isFrozen: columnResize.isFrozen,\n rootRef,\n startIndex,\n endIndex,\n containerHeight: win.containerHeight,\n containerWidth: win.containerWidth,\n });\n // The rest of `cols` is the header's business and goes there whole.\n const { hasColumns, visibleColumns, columnTemplate, widthVars, shouldShowToggle, recalculateColumns } = cols;\n visibleColumnsRef.current = visibleColumns;\n\n // Compose the forwarded handle from the hooks that own each piece: scroll\n // methods from the windowing engine, column controls from the column hooks.\n useImperativeHandle(ref, () => ({ ...win.scrollApi, recalculateColumns, resetColumnWidths: columnResize.reset }), [\n win.scrollApi,\n recalculateColumns,\n columnResize.reset,\n ]);\n\n // Dragging a row to position N is meaningless while the list decides the\n // order: the drop would be undone by the next sort pass.\n const dragBlockedBySort = isSorted && (reorderable || treeReorder);\n useEffect(() => {\n if (dragBlockedBySort)\n console.warn('VirtualList: row reordering is disabled while the list is sorted. Clear the sort to drag rows.');\n }, [dragBlockedBySort]);\n\n const drag = useRowDrag({\n reorderable: reorderable && !isSorted,\n treeReorder: treeReorder && !isSorted,\n onReorder,\n onTreeDrop,\n longPressDelay,\n dragHandle,\n treeIndentPx,\n keys,\n depths,\n isGroupAt,\n rootRef,\n keysRef,\n getVisibleRect: win.getVisibleRect,\n scrollBy: win.scrollBy,\n });\n\n const listId = useId();\n const rowDomId = (index: number) => `${listId}-row-${index}`;\n const nav = useRowNavigation({\n enabled: keyboardNavigation,\n tabAcrossRows,\n rowCount: rows.length,\n offsets,\n rootRef,\n headerRef,\n getVisibleSlice: win.getVisibleSlice,\n viewportHeight: win.viewportHeight,\n scrollToIndex: win.scrollApi.scrollToIndex,\n initialIndex: selectedKey != null ? Math.max(0, keys.indexOf(selectedKey)) : 0,\n multiSelect,\n onActivate: onRowClick && ((index: number) => onRowClick(rows[index], index)),\n onToggleSelect: (index) => selection.handleRowSelect(keys[index]),\n });\n\n const rowPaddingValue = typeof rowPadding === 'number' ? `${rowPadding}px` : rowPadding;\n\n const renderRowAt = (i: number) => {\n const item = rows[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 id={rowDomId(i)}\n index={i}\n top={offsets[i]}\n padding={rowPaddingValue}\n columnTemplate={columnTemplate}\n isSelected={isSelected}\n isActive={i === nav.activeIndex}\n manageTabStops={keyboardNavigation}\n isEntered={i === nav.enteredIndex}\n activeClassName={classNames?.activeRow}\n activeStyle={slotStyles?.activeRow}\n showDivider={showDivider}\n hover={rowHover}\n onClick={() => {\n if (drag.consumeSuppressedClick()) return;\n // Keep the arrows where the pointer last was.\n nav.setActiveIndex(i);\n onRowClick?.(item, i);\n }}\n observer={rowObserver}\n ariaRowIndex={hasColumns ? i + 2 : undefined}\n ariaPosInSet={hasColumns ? undefined : i + 1}\n ariaSetSize={hasColumns ? undefined : rows.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={text.selectRow}\n // One tab stop per rendered row, changing as the list scrolls,\n // would strand the focus the moment a row unmounts. Space on\n // the active row is the keyboard path instead.\n tabIndex={-1}\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-col-key={col.key}\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.renderCell(item, i)}\n </div>\n ))}\n </>\n ) : (\n renderRow?.(item, i)\n )}\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 // Same reason, one step further: the row being used holds the focus, and\n // unmounting it would drop that focus to the document body mid-scroll.\n if (nav.enteredIndex >= 0 && (nav.enteredIndex < startIndex || nav.enteredIndex > endIndex)) {\n visibleRows.push(renderRowAt(nav.enteredIndex));\n }\n\n // Navigation must not replace handlers the consumer passed. Theirs runs first,\n // and a `preventDefault` in it keeps the event: the navigation handlers all\n // check `defaultPrevented`.\n const containerProps = {\n ...nav.containerProps,\n onKeyDown: chain<React.KeyboardEvent<HTMLDivElement>>(rest.onKeyDown, nav.containerProps.onKeyDown),\n onFocus: chain<React.FocusEvent<HTMLDivElement>>(rest.onFocus, nav.containerProps.onFocus),\n onBlur: chain<React.FocusEvent<HTMLDivElement>>(rest.onBlur, nav.containerProps.onBlur),\n };\n\n return (\n <div\n {...rest}\n {...containerProps}\n ref={rootRef}\n className={cx(\n styles.virtualList,\n win.isWindowed && styles.virtualListWindowed,\n drag.draggingKey != null && styles.virtualListReordering,\n columnResize.isResizing && styles.virtualListResizing,\n className,\n classNames?.root,\n )}\n style={{ ...(win.isWindowed ? null : { height }), ...widthVars, ...style, ...slotStyles?.root }}\n role={ariaRoles?.container ?? (hasColumns ? 'grid' : 'list')}\n aria-rowcount={hasColumns ? rows.length + 1 : undefined}\n // Only a composite role may point at an active descendant, and the default\n // `list` is not one. In list mode, pass `ariaRoles` (e.g. listbox/option)\n // to have the active row announced.\n aria-activedescendant={\n nav.activeIndex >= 0 && (ariaRoles?.container ?? (hasColumns ? 'grid' : 'list')) !== 'list'\n ? rowDomId(nav.activeIndex)\n : undefined\n }\n >\n {hasColumns && (\n <VirtualListHeader<T>\n headerRef={headerRef}\n columns={columns!}\n cols={cols}\n resize={columnResize}\n sort={effectiveSort}\n onSort={handleHeaderSort}\n multiSelect={multiSelect}\n allSelected={selection.allSelected}\n someSelected={selection.someSelected}\n onSelectAll={selection.handleSelectAll}\n labels={text}\n classNames={classNames}\n styles={slotStyles}\n />\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\nexport default VirtualList;\n"],"mappings":"g3BAiBA,IAAM,GAA8C,CAClD,UAAW,aACX,cAAe,kBACf,cAAe,2BACf,cAAgB,GAAU,GAAG,EAAM,iBACnC,kBAAmB,qBACrB,EAoCA,SAAS,EAAS,EAA0C,EAAwC,CAElG,MADI,CAAC,GAAU,CAAC,EAAa,GAAU,EAC/B,GAAa,CACnB,EAAO,CAAK,EACZ,EAAK,CAAK,CACZ,CACF,CAEA,SAAS,EAAe,EAA4B,CAClD,GAAM,CACJ,OACA,SACA,aACA,YACA,UACA,UAAS,OACT,sBAAqB,GACrB,YAAW,EACX,UAAS,EACT,aACA,cACA,aACA,aACA,qBAAqB,GACrB,iBAAgB,GAChB,gBACA,qBACA,0BACA,oBACA,oBAAmB,GACnB,gBACA,wBACA,UACA,QACA,eACA,gBACA,oBACA,cACA,qBAAoB,IACpB,YAAY,GACZ,cAAc,GACd,gBACA,qBACA,cAAc,GACd,aACA,kBAAiB,IACjB,cAAc,GACd,eACA,UACA,cACA,gBAAe,GACf,cAAa,GACb,eAAc,GACd,YAAW,GACX,aACA,SACA,aACA,OAAQ,EACR,GAAG,GACD,EAGE,EAAgB,EAAM,cAAgB,MAAQ,EAAM,SAAW,IAAA,GACrE,MAAgB,CACV,GACF,QAAQ,KACN,uGACF,CACJ,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,EAAO,EAAU,cAAe,GAAQ,EAAc,EACtD,CAAE,OAAM,iBAAe,WAAU,qBAAqB,GAAc,CACxE,SACA,UACA,QACA,eACA,eACF,CAAC,EAEK,EAAS,IACZ,EAAS,IAAoC,EAAa,EAAW,EAAM,CAAK,EAAI,EACrF,CAAC,CAAU,CACb,EACM,EAAO,MAAc,EAAK,KAAK,EAAM,IAAM,EAAO,EAAM,CAAC,CAAC,EAAG,CAAC,EAAM,CAAM,CAAC,EAC3E,GAAS,MACN,EAAe,EAAK,KAAK,EAAM,IAAM,EAAa,EAAM,CAAC,CAAC,EAAI,CAAC,EACtE,CAAC,EAAM,CAAY,CACrB,EACM,GAAY,GAAa,GAAe,EAAU,EAAQ,EAAK,GAAI,CAAC,EAAI,GAAQ,CAAC,EAAS,CAAI,CAAC,EAE/F,EAAM,EAAoB,CAC9B,MAAO,EACP,OACA,aACA,sBACA,UACA,YACA,cACA,qBACA,YACA,eACF,CAAC,EACK,CAAE,UAAS,YAAW,eAAa,WAAS,UAAS,eAAa,aAAY,YAAa,EAK3F,EAAoB,GAA+B,CAAC,CAAC,EACrD,EAAe,GAAmB,CACtC,UACA,oBACA,oBACA,gBACA,wBACA,oBACA,SACF,CAAC,EAEK,EAAY,EAAgB,CAAE,MAAO,EAAM,SAAQ,cAAa,gBAAc,oBAAkB,CAAC,EACjG,CAAE,yBAA0B,EAE5B,EAAO,GAAc,CACzB,UACA,MAAO,EACP,cACA,qBACA,0BACA,oBACA,oBACA,WAAY,EAAa,OACzB,SAAU,EAAa,SACvB,UACA,aACA,WACA,gBAAiB,EAAI,gBACrB,eAAgB,EAAI,cACtB,CAAC,EAEK,CAAE,aAAY,kBAAgB,kBAAgB,aAAW,oBAAkB,uBAAuB,EACxG,EAAkB,QAAU,GAI5B,GAAoB,QAAY,CAAE,GAAG,EAAI,UAAW,sBAAoB,kBAAmB,EAAa,KAAM,GAAI,CAChH,EAAI,UACJ,GACA,EAAa,KACf,CAAC,EAID,IAAM,GAAoB,IAAa,GAAe,GACtD,MAAgB,CACV,IACF,QAAQ,KAAK,gGAAgG,CACjH,EAAG,CAAC,EAAiB,CAAC,EAEtB,IAAM,EAAO,GAAW,CACtB,YAAa,GAAe,CAAC,EAC7B,YAAa,GAAe,CAAC,EAC7B,aACA,cACA,kBACA,cACA,gBACA,OACA,UACA,aACA,UACA,WACA,eAAgB,EAAI,eACpB,SAAU,EAAI,QAChB,CAAC,EAEK,GAAS,GAAM,EACf,GAAY,GAAkB,GAAG,GAAO,OAAO,IAC/C,EAAM,GAAiB,CAC3B,QAAS,EACT,iBACA,SAAU,EAAK,OACf,UACA,UACA,YACA,gBAAiB,EAAI,gBACrB,eAAgB,EAAI,eACpB,cAAe,EAAI,UAAU,cAC7B,aAAc,GAAe,KAAgD,EAAzC,KAAK,IAAI,EAAG,EAAK,QAAQ,CAAW,CAAC,EACzE,cACA,WAAY,IAAgB,GAAkB,EAAW,EAAK,GAAQ,CAAK,GAC3E,eAAiB,GAAU,EAAU,gBAAgB,EAAK,EAAM,CAClE,CAAC,EAEK,GAAkB,OAAO,GAAe,SAAW,GAAG,EAAW,IAAM,EAEvE,EAAe,GAAc,CACjC,IAAM,EAAO,EAAK,GACZ,EAAM,EAAO,EAAM,CAAC,EACpB,EAAc,GAAe,MAAQ,IAAQ,GAAgB,EAAsB,IAAI,CAAG,EAC1F,EAAY,EAAK,gBAAgB,EAAG,CAAG,EAE7C,OACE,EAAC,GAAD,CAEE,GAAI,GAAS,CAAC,EACd,MAAO,EACP,IAAK,EAAQ,GACb,QAAS,GACO,kBACJ,aACZ,SAAU,IAAM,EAAI,YACpB,eAAgB,EAChB,UAAW,IAAM,EAAI,aACrB,gBAAiB,GAAY,UAC7B,YAAa,GAAY,UACZ,eACb,MAAO,GACP,YAAe,CACT,EAAK,uBAAuB,IAEhC,EAAI,eAAe,CAAC,EACpB,IAAa,EAAM,CAAC,EACtB,EACA,SAAU,GACV,aAAc,EAAa,EAAI,EAAI,IAAA,GACnC,aAAc,EAAa,IAAA,GAAY,EAAI,EAC3C,YAAa,EAAa,IAAA,GAAY,EAAK,OAC3C,QAAS,GAAW,MAAQ,EAAa,MAAQ,YACjD,oBAAqB,GACrB,GAAI,EACJ,uBAAwB,GAAY,cACpC,mBAAoB,GAAY,cAChC,aAAc,GAAY,IAC1B,SAAU,GAAY,IAErB,SAAA,EACC,EAAA,GAAA,CAAA,SAAA,CACG,GACC,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,sBAAuB,GAAY,UAAU,EAClE,MAAO,GAAY,WACnB,KAAK,WACL,QAAU,GAAM,EAAE,gBAAgB,EAElC,SAAA,EAAC,EAAD,CACE,SAAU,EAAsB,IAAI,CAAG,EACvC,aAAgB,EAAU,gBAAgB,CAAG,EAC7C,aAAY,EAAK,UAIjB,SAAU,EACX,CAAA,CACE,CAAA,EAEN,GAAe,IAAK,GACnB,EAAC,MAAD,CAEE,UAAW,EAAG,EAAO,gBAAiB,GAAY,IAAI,EACtD,MAAO,GAAY,KACnB,KAAK,WACL,eAAc,EAAI,IAClB,eAAc,EAAI,MAAM,OAAS,MAAQ,EAAI,IAAM,IAAA,GAElD,SAAA,EAAI,WAAW,EAAM,CAAC,CACpB,EARE,EAAI,GAQN,CACN,CACD,CAAA,CAAA,EAEF,KAAY,EAAM,CAAC,CAEX,EApEL,CAoEK,CAEhB,EAEM,EAAiC,CAAC,EACxC,IAAK,IAAI,EAAI,EAAY,GAAK,EAAU,IAAK,EAAY,KAAK,EAAY,CAAC,CAAC,EAM5E,IAAM,EAAe,EAAK,aAAe,KAAwC,GAAjC,EAAK,QAAQ,EAAK,WAAW,EACzE,GAAgB,IAAM,EAAe,GAAc,EAAe,IACpE,EAAY,KAAK,EAAY,CAAY,CAAC,EAKxC,EAAI,cAAgB,IAAM,EAAI,aAAe,GAAc,EAAI,aAAe,IAChF,EAAY,KAAK,EAAY,EAAI,YAAY,CAAC,EAMhD,IAAM,GAAiB,CACrB,GAAG,EAAI,eACP,UAAW,EAA2C,EAAK,UAAW,EAAI,eAAe,SAAS,EAClG,QAAS,EAAwC,EAAK,QAAS,EAAI,eAAe,OAAO,EACzF,OAAQ,EAAwC,EAAK,OAAQ,EAAI,eAAe,MAAM,CACxF,EAEA,OACE,EAAC,MAAD,CACE,GAAI,EACJ,GAAI,GACJ,IAAK,EACL,UAAW,EACT,EAAO,YACP,EAAI,YAAc,EAAO,oBACzB,EAAK,aAAe,MAAQ,EAAO,sBACnC,EAAa,YAAc,EAAO,oBAClC,GACA,GAAY,IACd,EACA,MAAO,CAAE,GAAI,EAAI,WAAa,KAAO,CAAE,SAAO,EAAI,GAAG,GAAW,GAAG,GAAO,GAAG,GAAY,IAAK,EAC9F,KAAM,GAAW,YAAc,EAAa,OAAS,QACrD,gBAAe,EAAa,EAAK,OAAS,EAAI,IAAA,GAI9C,wBACE,EAAI,aAAe,IAAM,GAAW,YAAc,EAAa,OAAS,WAAa,OACjF,GAAS,EAAI,WAAW,EACxB,IAAA,GArBR,SAAA,CAwBG,GACC,EAAC,EAAD,CACa,YACF,UACH,OACN,OAAQ,EACR,KAAM,GACN,OAAQ,GACK,cACb,YAAa,EAAU,YACvB,aAAc,EAAU,aACxB,YAAa,EAAU,gBACvB,OAAQ,EACI,aACZ,OAAQ,CACT,CAAA,EAEF,EACC,EAAC,MAAD,CAAK,UAAW,EAAO,uBACrB,SAAA,EAAC,EAAD,CAAgB,UAAW,EAAO,kBAAqB,CAAA,CACpD,CAAA,EAEL,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,gBAAiB,GAAY,IAAI,EACtD,MAAO,CAAE,OAAQ,GAAa,GAAG,GAAY,IAAK,EAEjD,SAAA,CACE,CAAA,EAEN,EAAI,qBACH,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,4BAA6B,GAAY,gBAAgB,EAC9E,MAAO,GAAY,iBAEnB,SAAA,EAAC,EAAD,CAAgB,UAAW,EAAO,kBAAqB,CAAA,CACpD,CAAA,CAEJ,GAET"}
|
|
1
|
+
{"version":3,"file":"virtualList.mjs","names":[],"sources":["../../../../package/common/virtualList/virtualList.tsx"],"sourcesContent":["import React, { useMemo, useCallback, useEffect, useId, useImperativeHandle, useRef } from 'react';\nimport cx from 'classnames';\nimport styles from './virtualList.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport Checkbox from '../checkbox';\nimport VirtualRow from './virtualRow';\nimport VirtualListHeader from './virtualListHeader';\nimport { useVirtualWindow } from './useVirtualWindow';\nimport { useSelection } from './useSelection';\nimport { useColumns } from './useColumns';\nimport { useRowDrag } from './useRowDrag';\nimport { useSorting } from './useSorting';\nimport { useColumnResize } from './useColumnResize';\nimport { useRowNavigation } from './useRowNavigation';\nimport { useLabels } from '../configProvider';\nimport type { VirtualListColumn, VirtualListLabels, VirtualListProps } from './virtualList.types';\n\nconst DEFAULT_LABELS: Required<VirtualListLabels> = {\n selectRow: 'Select row',\n selectAllRows: 'Select all rows',\n toggleColumns: 'Toggle column visibility',\n columnsHidden: (count) => `${count} columns hidden`,\n resetColumnWidths: 'Reset column widths',\n};\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 compareSortValues,\n isColumnSortable,\n isEmptySortValue,\n nextSort,\n sortItems,\n} from './virtualList.utils';\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n// VirtualListInner wires the hooks together and renders the two pieces of\n// markup. Each concern lives in its own module:\n// useSorting — table mode: header sort state, and the sorted row order\n// useVirtualWindow — generic scroll / measurement / windowing (all modes)\n// useColumnResize — table mode: user column widths, and the drag that sets them\n// useSelection — multi-row selection\n// useColumns — table mode: columns, visibility, persistence, fit widths\n// useRowDrag — reorder + tree drag-and-drop (mouse + touch)\n// useRowNavigation — arrow-key navigation over the rows\n// virtualListHeader — the header row: sorting, resizing, the column menu\n// virtualRow — one positioned row, with its drag wiring\n//\n// The hook order is not free: useColumnResize decides whether the layout is\n// frozen, which useColumns needs to build the grid template.\n\n/** One handler after the other, or whichever of the two exists. */\nfunction chain<E>(theirs: ((event: E) => void) | undefined, ours: ((event: E) => void) | undefined) {\n if (!theirs || !ours) return theirs ?? ours;\n return (event: E) => {\n theirs(event);\n ours(event);\n };\n}\n\nfunction VirtualList<T>(props: VirtualListProps<T>) {\n const {\n ref,\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 keyboardNavigation = true,\n tabAcrossRows = false,\n scrollParent,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n resizableColumns = false,\n columnWidths,\n onColumnWidthsChange,\n labels,\n sort,\n defaultSort,\n onSortChange,\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 } = props;\n // Read off the raw props: the destructured value carries a default and so\n // cannot tell a passed '100%' from an omitted one.\n const heightIgnored = props.scrollParent != null && props.height !== undefined;\n useEffect(() => {\n if (heightIgnored)\n console.warn(\n 'VirtualList: `height` is ignored alongside `scrollParent`, which leaves the list no viewport to size.',\n );\n }, [heightIgnored]);\n\n const text = useLabels('VirtualList', labels, DEFAULT_LABELS);\n const { rows, effectiveSort, isSorted, handleHeaderSort } = useSorting<T>({\n items,\n columns,\n sort,\n defaultSort,\n onSortChange,\n });\n\n const getKey = useCallback(\n (item: T, index: number): string | number => (getItemKey ? getItemKey(item, index) : index),\n [getItemKey],\n );\n const keys = useMemo(() => rows.map((item, i) => getKey(item, i)), [rows, getKey]);\n const depths = useMemo(\n () => (getItemDepth ? rows.map((item, i) => getItemDepth(item, i)) : []),\n [rows, getItemDepth],\n );\n const isGroupAt = useCallback((i: number) => (isGroup ? isGroup(rows[i], i) : false), [isGroup, rows]);\n\n const win = useVirtualWindow<T>({\n items: rows,\n keys,\n getItemKey,\n estimatedRowHeight,\n rowGap,\n overscan,\n onLoadMore,\n loadMoreThreshold,\n isLoading,\n scrollParent,\n });\n const { rootRef, headerRef, rowObserver, keysRef, offsets, totalHeight, startIndex, endIndex } = win;\n\n // Filled from `cols` below: the resize hook only reads the visible set when a\n // handle is actually used, which is what lets it run before the hook that\n // derives it.\n const visibleColumnsRef = useRef<VirtualListColumn<T>[]>([]);\n const columnResize = useColumnResize<T>({\n columns,\n visibleColumnsRef,\n resizableColumns,\n columnWidths,\n onColumnWidthsChange,\n persistColumnsKey,\n rootRef,\n });\n\n const selection = useSelection<T>({ items: rows, getKey, multiSelect, selectedKeys, onSelectionChange });\n const { effectiveSelectedKeys } = selection;\n\n const cols = useColumns<T>({\n columns,\n items: rows,\n multiSelect,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n userWidths: columnResize.widths,\n isFrozen: columnResize.isFrozen,\n rootRef,\n startIndex,\n endIndex,\n containerHeight: win.containerHeight,\n containerWidth: win.containerWidth,\n isLoading,\n });\n // The rest of `cols` is the header's business and goes there whole.\n const { hasColumns, visibleColumns, columnTemplate, widthVars, shouldShowToggle, recalculateColumns } = cols;\n visibleColumnsRef.current = visibleColumns;\n\n // Compose the forwarded handle from the hooks that own each piece: scroll\n // methods from the windowing engine, column controls from the column hooks.\n useImperativeHandle(ref, () => ({ ...win.scrollApi, recalculateColumns, resetColumnWidths: columnResize.reset }), [\n win.scrollApi,\n recalculateColumns,\n columnResize.reset,\n ]);\n\n // Dragging a row to position N is meaningless while the list decides the\n // order: the drop would be undone by the next sort pass.\n const dragBlockedBySort = isSorted && (reorderable || treeReorder);\n useEffect(() => {\n if (dragBlockedBySort)\n console.warn('VirtualList: row reordering is disabled while the list is sorted. Clear the sort to drag rows.');\n }, [dragBlockedBySort]);\n\n const drag = useRowDrag({\n reorderable: reorderable && !isSorted,\n treeReorder: treeReorder && !isSorted,\n onReorder,\n onTreeDrop,\n longPressDelay,\n dragHandle,\n treeIndentPx,\n keys,\n depths,\n isGroupAt,\n rootRef,\n keysRef,\n getVisibleRect: win.getVisibleRect,\n scrollBy: win.scrollBy,\n });\n\n const listId = useId();\n const rowDomId = (index: number) => `${listId}-row-${index}`;\n const nav = useRowNavigation({\n enabled: keyboardNavigation,\n tabAcrossRows,\n rowCount: rows.length,\n offsets,\n rootRef,\n headerRef,\n getVisibleSlice: win.getVisibleSlice,\n viewportHeight: win.viewportHeight,\n scrollToIndex: win.scrollApi.scrollToIndex,\n initialIndex: selectedKey != null ? Math.max(0, keys.indexOf(selectedKey)) : 0,\n multiSelect,\n onActivate: onRowClick && ((index: number) => onRowClick(rows[index], index)),\n onToggleSelect: (index) => selection.handleRowSelect(keys[index]),\n });\n\n const rowPaddingValue = typeof rowPadding === 'number' ? `${rowPadding}px` : rowPadding;\n\n const renderRowAt = (i: number) => {\n const item = rows[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 id={rowDomId(i)}\n index={i}\n top={offsets[i]}\n padding={rowPaddingValue}\n columnTemplate={columnTemplate}\n isSelected={isSelected}\n isActive={i === nav.activeIndex}\n manageTabStops={keyboardNavigation}\n isEntered={i === nav.enteredIndex}\n activeClassName={classNames?.activeRow}\n activeStyle={slotStyles?.activeRow}\n showDivider={showDivider}\n hover={rowHover}\n onClick={() => {\n if (drag.consumeSuppressedClick()) return;\n // Keep the arrows where the pointer last was.\n nav.setActiveIndex(i);\n onRowClick?.(item, i);\n }}\n observer={rowObserver}\n ariaRowIndex={hasColumns ? i + 2 : undefined}\n ariaPosInSet={hasColumns ? undefined : i + 1}\n ariaSetSize={hasColumns ? undefined : rows.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={text.selectRow}\n // One tab stop per rendered row, changing as the list scrolls,\n // would strand the focus the moment a row unmounts. Space on\n // the active row is the keyboard path instead.\n tabIndex={-1}\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-col-key={col.key}\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.renderCell(item, i)}\n </div>\n ))}\n </>\n ) : (\n renderRow?.(item, i)\n )}\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 // Same reason, one step further: the row being used holds the focus, and\n // unmounting it would drop that focus to the document body mid-scroll.\n if (nav.enteredIndex >= 0 && (nav.enteredIndex < startIndex || nav.enteredIndex > endIndex)) {\n visibleRows.push(renderRowAt(nav.enteredIndex));\n }\n\n // Navigation must not replace handlers the consumer passed. Theirs runs first,\n // and a `preventDefault` in it keeps the event: the navigation handlers all\n // check `defaultPrevented`.\n const containerProps = {\n ...nav.containerProps,\n onKeyDown: chain<React.KeyboardEvent<HTMLDivElement>>(rest.onKeyDown, nav.containerProps.onKeyDown),\n onFocus: chain<React.FocusEvent<HTMLDivElement>>(rest.onFocus, nav.containerProps.onFocus),\n onBlur: chain<React.FocusEvent<HTMLDivElement>>(rest.onBlur, nav.containerProps.onBlur),\n };\n\n return (\n <div\n {...rest}\n {...containerProps}\n ref={rootRef}\n className={cx(\n styles.virtualList,\n win.isWindowed && styles.virtualListWindowed,\n drag.draggingKey != null && styles.virtualListReordering,\n columnResize.isResizing && styles.virtualListResizing,\n className,\n classNames?.root,\n )}\n style={{ ...(win.isWindowed ? null : { height }), ...widthVars, ...style, ...slotStyles?.root }}\n role={ariaRoles?.container ?? (hasColumns ? 'grid' : 'list')}\n aria-rowcount={hasColumns ? rows.length + 1 : undefined}\n // Only a composite role may point at an active descendant, and the default\n // `list` is not one. In list mode, pass `ariaRoles` (e.g. listbox/option)\n // to have the active row announced.\n aria-activedescendant={\n nav.activeIndex >= 0 && (ariaRoles?.container ?? (hasColumns ? 'grid' : 'list')) !== 'list'\n ? rowDomId(nav.activeIndex)\n : undefined\n }\n >\n {hasColumns && (\n <VirtualListHeader<T>\n headerRef={headerRef}\n columns={columns!}\n cols={cols}\n resize={columnResize}\n sort={effectiveSort}\n onSort={handleHeaderSort}\n multiSelect={multiSelect}\n allSelected={selection.allSelected}\n someSelected={selection.someSelected}\n onSelectAll={selection.handleSelectAll}\n labels={text}\n classNames={classNames}\n styles={slotStyles}\n />\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\nexport default VirtualList;\n"],"mappings":"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"}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";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{useLabels as r}from"./common/configProvider/useLabels.mjs";import{usePresentationDefault as i}from"./common/configProvider/usePresentationDefault.mjs";import{Presentation as a}from"./common/configProvider/presentation.types.mjs";import o from"./common/accordion/accordion.mjs";import s from"./common/loading/spinnerLoading/index.mjs";import{ButtonSize as c,ButtonStyleType as l,ButtonType as u}from"./common/button/button.types.mjs";import d from"./common/ripple/ripple.mjs";import f from"./common/button/button.mjs";import p from"./common/actionButtons/actionButtons.mjs";import m from"./common/interactableDiv/index.mjs";import h from"./common/actionIcon/actionIcon.mjs";import{AlertStyleType as g}from"./common/alert/alert.types.mjs";import _ from"./common/alert/alert.mjs";import v from"./common/animatedLogo/animatedLogo.mjs";import{AnimatedTextUnit as y,AnimatedTextVariant as b}from"./common/animatedText/animatedText.types.mjs";import x from"./common/animatedText/animatedText.mjs";import{BadgePosition as S,BadgeStyleType as C}from"./common/badge/badge.types.mjs";import w from"./common/badge/badge.mjs";import T from"./common/avatar/avatar.mjs";import E from"./common/avatar/avatarGroup.mjs";import D from"./common/bodyEnd/bodyEnd.mjs";import{PopoverAlign as O,PopoverPlacement as k,PopoverTrigger as A}from"./common/popover/popover.types.mjs";import{tabbablesIn as j}from"./common/hooks/useFocusBoundary.mjs";import M from"./common/hooks/useMediaQuery.mjs";import N from"./common/hooks/useCoarsePointer.mjs";import{useVisualViewportSize as P}from"./common/hooks/useVisualViewportSize.mjs";import{useOverlay as F}from"./common/hooks/useOverlay.mjs";import I from"./common/popover/popover.mjs";import L from"./common/breadcrumb/breadcrumb.mjs";import{ButtonGroupOrientation as R}from"./common/buttonGroup/buttonGroup.types.mjs";import z from"./common/buttonGroup/buttonGroup.mjs";import{CardStyleType as B}from"./common/card/card.types.mjs";import V from"./common/card/Card.mjs";import H from"./common/card/CardHeader.mjs";import U from"./common/card/CardMedia.mjs";import W from"./common/card/CardContent.mjs";import G from"./common/card/CardActions.mjs";import K from"./common/carousel/carousel.mjs";import q from"./common/checkbox/checkbox.mjs";import{ChipStyleType as J}from"./common/chip/chip.types.mjs";import Y from"./common/chip/chip.mjs";import X from"./common/chip/chipContainer.mjs";import Z from"./common/tooltip/tooltip.mjs";import{InputIconPosition as Q,InputType as $}from"./common/input/input.types.mjs";import ee from"./common/input/input.mjs";import te from"./common/colorPicker/colorPicker.mjs";import{useScrollEdges as ne}from"./common/hooks/useScrollEdges.mjs";import re from"./common/modal/modal.mjs";import ie,{formatHotkey as ae}from"./common/hooks/useHotkeys.mjs";import{isMenuAction as oe,isMenuHeading as se,isMenuSeparator as ce}from"./common/menu/menu.types.mjs";import le from"./common/commandPalette/commandPalette.mjs";import ue from"./common/confirmModal/confirmModal.mjs";import de from"./common/hooks/useClipboard.mjs";import fe from"./common/copyButton/copyButton.mjs";import{getLocale as pe,mapLocale as me,setLocale as he}from"./services/localization.mjs";import{dateToDay as ge,dayToDate as _e}from"./common/utils/day.mjs";import ve from"./common/dropdown/dropdown.mjs";import ye from"./common/datePicker/datePicker.mjs";import{DividerOrientation as be,DividerTextPosition as xe}from"./common/divider/divider.types.mjs";import Se from"./common/divider/divider.mjs";import Ce from"./common/drawer/drawer.mjs";import{DropZoneReturnType as we,DropZoneStatus as Te}from"./common/dropZone/dropZone.types.mjs";import Ee from"./common/dropZone/dropZone.mjs";import De from"./common/emptyState/emptyState.mjs";import{useSwipeDismiss as Oe}from"./common/hooks/useSwipeDismiss.mjs";import{showToast as ke}from"./common/toast/toastService.mjs";import Ae from"./common/toast/toastProvider.mjs";import je from"./common/errorBoundary/errorBoundary.mjs";import Me from"./common/fab/fab.mjs";import Ne from"./common/flip/flip.mjs";import{DoorSwing as Pe,OpeningKind as Fe,PlanIssueKind as Ie,PlanUnitSystem as Le,WallType as Re}from"./common/floorPlan/floorPlan.types.mjs";import{MIN_OPENING_WIDTH as ze,MIN_WALL_LENGTH as Be}from"./common/floorPlan/floorPlan.geometry.mjs";import{DEFAULT_WALL_ATTRS as Ve,addOpening as He,addRect as Ue,addWall as We,cleanupPlan as Ge,detachWall as Ke,dissolveNode as qe,mergeNodes as Je,moveNode as Ye,removeOpening as Xe,removeWall as Ze,scalePlan as Qe,splitWall as $e,transformPlan as et,updateOpening as tt,validatePlan as nt,wallLength as rt,weldShortWalls as it}from"./common/floorPlan/floorPlan.graph.mjs";import{MIN_FLOOR_HEIGHT as at,addFloor as ot,duplicateFloor as st,emptyFloor as ct,emptyFloorPlan as lt,floorBelow as ut,floorBounds as dt,floorIndex as ft,getFloor as pt,moveFloor as mt,removeFloor as ht,renameFloor as gt,setFloor as _t,setFloorHeight as vt,updateFloor as yt}from"./common/floorPlan/floorPlan.plan.mjs";import{deriveFaces as bt,nodeDegrees as xt}from"./common/floorPlan/floorPlan.faces.mjs";import{commitDerivation as St,derivePlan as Ct,pruneUnmatchedRooms as wt,roomAtPoint as Tt}from"./common/floorPlan/floorPlan.rooms.mjs";import{buildWallPaths as Et,openingGeometry as Dt,wallCentrelineSpans as Ot}from"./common/floorPlan/floorPlan.path.mjs";import{HIT_PX as kt,HIT_PX_COARSE as At,hitTest as jt,selectionsEqual as Mt,worldTolerances as Nt}from"./common/floorPlan/floorPlan.hit.mjs";import{DEFAULT_SNAP_OPTIONS as Pt,SnapKind as Ft,clientToWorld as It,resolveSnap as Lt,screenScale as Rt}from"./common/floorPlan/floorPlan.snap.mjs";import{PLAN_FORMAT_VERSION as zt,planFromJson as Bt,planToJson as Vt}from"./common/floorPlan/floorPlan.json.mjs";import{buildPlanMesh as Ht}from"./common/floorPlan/floorPlan.mesh.mjs";import{planFromLegacySvg as Ut}from"./common/floorPlan/legacySvg.mjs";import Wt from"./common/iconPicker/iconPicker.mjs";import Gt from"./common/idleManager/idleManager.mjs";import Kt from"./common/inputDropdown/inputDropdown.mjs";import qt from"./common/kanbanBoard/KanbanColumn.mjs";import Jt from"./common/kanbanBoard/KanbanBoard.mjs";import Yt from"./common/searchInput/searchInput.mjs";import Xt from"./common/klipyPicker/klipyPicker.mjs";import Zt from"./common/menu/menu.mjs";import{menuHotkeys as Qt}from"./common/menu/menuHotkeys.mjs";import $t from"./common/multiSelect/multiSelect.mjs";import en from"./common/numberInput/index.mjs";import tn from"./common/optionPicker/optionPicker.mjs";import{OtpInputCharset as nn}from"./common/otpInput/otpInput.types.mjs";import rn from"./common/otpInput/otpInput.mjs";import an from"./common/overscroll/overscroll.mjs";import on from"./common/pagination/pagination.mjs";import sn from"./common/progressBar/progressBar.mjs";import{RadioGroupOrientation as cn}from"./common/radioGroup/radioGroup.types.mjs";import ln from"./common/radioGroup/radioGroup.mjs";import un from"./common/rating/rating.mjs";import dn from"./common/revealLens/revealLens.mjs";import fn from"./common/roomDrawer/roomDrawer.mjs";import pn from"./common/roomViewer/roomViewer.mjs";import{ScrollFadeAxis as mn}from"./common/scrollFade/scrollFade.types.mjs";import hn from"./common/scrollFade/scrollFade.mjs";import gn from"./common/scrollbarProvider/index.mjs";import{SectionHeaderSize as _n}from"./common/sectionHeader/sectionHeader.types.mjs";import vn from"./common/sectionHeader/sectionHeader.mjs";import{SkeletonAnimation as yn,SkeletonVariant as bn}from"./common/skeleton/skeleton.types.mjs";import xn from"./common/skeleton/skeleton.mjs";import Sn from"./common/slider/slider.mjs";import Cn from"./common/splitButton/splitButton.mjs";import{StepperAlignment as wn,StepperCollapse as Tn,StepperLabelPlacement as En,StepperStyleType as Dn}from"./common/stepper/stepper.types.mjs";import On from"./common/stepper/stepper.mjs";import kn from"./common/sticky/sticky.mjs";import An from"./common/switch/switch.mjs";import jn from"./common/tabHeader/tabHeader.mjs";import Mn from"./common/textarea/textarea.mjs";import{defaultTheme as Nn}from"./common/themeProvider/defaultTheme.mjs";import Pn from"./common/themeProvider/themeProvider.mjs";import{lightTheme as Fn}from"./common/themeProvider/lightTheme.mjs";import{useTheme as In}from"./common/themeProvider/useTheme.mjs";import Ln,{TiltGroupContext as Rn,useTiltGroup as zn}from"./common/tiltGroup/tiltGroup.mjs";import{defaultTiltEasing as Bn}from"./common/tilt/tiltMath.mjs";import Vn from"./common/tilt/tilt.mjs";import Hn from"./common/timeInput/timeInput.mjs";import{TimelineAlignment as Un,TimelineItemStatus as Wn}from"./common/timeline/timeline.types.mjs";import Gn from"./common/timeline/timeline.mjs";import Kn from"./common/timer/timer.mjs";import qn from"./common/virtualList/virtualList.mjs";import{flattenTree as Jn}from"./common/tree/flattenTree.mjs";import Yn from"./common/tree/tree.mjs";import{WeatherType as Xn}from"./common/weatherIcon/weatherIcon.types.mjs";import Zn from"./common/weatherIcon/weatherIcon.mjs";import Qn from"./common/wizard/wizard.mjs";import $n from"./services/formValidation/FormValidatorGroupWithForm.mjs";import er from"./services/formValidation/validatableComponent.mjs";import{useFormValidatorGroup as tr}from"./services/formValidation/useFormValidatorGroup.mjs";import{FormValidator as nr,Validators as rr,useFormValidator as ir}from"./services/formValidation/index.mjs";import{hasEightPasswordChars as ar,hasOnePasswordDigit as or,hasOnePasswordLetter as sr,isBic as cr,isDate as lr,isDay as ur,isEmail as dr,isISODate as fr,isNumber as pr,isPassword as mr,isURL as hr}from"@ahrowe/form-validation";export{o as Accordion,e as AccordionStyleType,p as ActionButtons,h as ActionIcon,_ as Alert,g as AlertStyleType,v as AnimatedLogo,x as AnimatedText,y as AnimatedTextUnit,b as AnimatedTextVariant,T as Avatar,E as AvatarGroup,w as Badge,S as BadgePosition,C as BadgeStyleType,D as BodyEnd,L as Breadcrumb,f as Button,z as ButtonGroup,R as ButtonGroupOrientation,c as ButtonSize,l as ButtonStyleType,u as ButtonType,V as Card,G as CardActions,W as CardContent,H as CardHeader,U as CardMedia,B as CardStyleType,K as Carousel,q as Checkbox,Y as Chip,X as ChipContainer,J as ChipStyleType,te as ColorPicker,le as CommandPalette,t as ConfigProvider,ue as ConfirmModal,fe as CopyButton,Pt as DEFAULT_SNAP_OPTIONS,Ve as DEFAULT_WALL_ATTRS,ye as DatePicker,Se as Divider,be as DividerOrientation,xe as DividerTextPosition,Pe as DoorSwing,Ce as Drawer,Ee as DropZone,we as DropZoneReturnType,Te as DropZoneStatus,ve as Dropdown,De as EmptyState,je as ErrorBoundary,Me as Fab,Ne as Flip,nr as FormValidator,$n as FormValidatorGroup,kt as HIT_PX,At as HIT_PX_COARSE,Wt as IconPicker,Gt as IdleManager,ee as Input,Kt as InputDropdown,Q as InputIconPosition,$ as InputType,m as InteractableDiv,Jt as KanbanBoard,qt as KanbanColumn,Xt as KlipyPicker,at as MIN_FLOOR_HEIGHT,ze as MIN_OPENING_WIDTH,Be as MIN_WALL_LENGTH,Zt as Menu,re as Modal,$t as MultiSelect,en as NumberInput,Fe as OpeningKind,tn as OptionPicker,rn as OtpInput,nn as OtpInputCharset,an as Overscroll,zt as PLAN_FORMAT_VERSION,on as Pagination,Ie as PlanIssueKind,Le as PlanUnitSystem,I as Popover,O as PopoverAlign,k as PopoverPlacement,A as PopoverTrigger,a as Presentation,sn as ProgressBar,ln as RadioGroup,cn as RadioGroupOrientation,un as Rating,dn as RevealLens,d as Ripple,fn as RoomDrawer,pn as RoomViewer,hn as ScrollFade,mn as ScrollFadeAxis,gn as ScrollbarProvider,Yt as SearchInput,vn as SectionHeader,_n as SectionHeaderSize,xn as Skeleton,yn as SkeletonAnimation,bn as SkeletonVariant,Sn as Slider,Ft as SnapKind,s as SpinnerLoading,Cn as SplitButton,On as Stepper,wn as StepperAlignment,Tn as StepperCollapse,En as StepperLabelPlacement,Dn as StepperStyleType,kn as Sticky,An as Switch,jn as TabHeader,Mn as Textarea,Pn as ThemeProvider,Vn as Tilt,Ln as TiltGroup,Rn as TiltGroupContext,Hn as TimeInput,Gn as Timeline,Un as TimelineAlignment,Wn as TimelineItemStatus,Kn as Timer,Ae as ToastProvider,Z as Tooltip,Yn as Tree,er as ValidatableComponent,rr as Validators,qn as VirtualList,Re as WallType,Zn as WeatherIcon,Xn as WeatherType,Qn as Wizard,ot as addFloor,He as addOpening,Ue as addRect,We as addWall,Ht as buildPlanMesh,Et as buildWallPaths,Ge as cleanupPlan,It as clientToWorld,St as commitDerivation,ge as dateToDay,_e as dayToDate,Nn as defaultTheme,Bn as defaultTiltEasing,bt as deriveFaces,Ct as derivePlan,Ke as detachWall,qe as dissolveNode,st as duplicateFloor,ct as emptyFloor,lt as emptyFloorPlan,Jn as flattenTree,ut as floorBelow,dt as floorBounds,ft as floorIndex,ae as formatHotkey,pt as getFloor,pe as getLocale,ar as hasEightPasswordChars,or as hasOnePasswordDigit,sr as hasOnePasswordLetter,jt as hitTest,cr as isBic,lr as isDate,ur as isDay,dr as isEmail,fr as isISODate,oe as isMenuAction,se as isMenuHeading,ce as isMenuSeparator,pr as isNumber,mr as isPassword,hr as isURL,Fn as lightTheme,me as mapLocale,Qt as menuHotkeys,Je as mergeNodes,mt as moveFloor,Ye as moveNode,xt as nodeDegrees,Dt as openingGeometry,Bt as planFromJson,Ut as planFromLegacySvg,Vt as planToJson,wt as pruneUnmatchedRooms,ht as removeFloor,Xe as removeOpening,Ze as removeWall,gt as renameFloor,Lt as resolveSnap,Tt as roomAtPoint,Qe as scalePlan,Rt as screenScale,Mt as selectionsEqual,_t as setFloor,vt as setFloorHeight,he as setLocale,ke as showToast,$e as splitWall,j as tabbablesIn,et as transformPlan,yt as updateFloor,tt as updateOpening,de as useClipboard,N as useCoarsePointer,n as useComponentDefaults,ir as useFormValidator,tr as useFormValidatorGroup,ie as useHotkeys,r as useLabels,M as useMediaQuery,F as useOverlay,i as usePresentationDefault,ne as useScrollEdges,Oe as useSwipeDismiss,In as useTheme,zn as useTiltGroup,P as useVisualViewportSize,nt as validatePlan,Ot as wallCentrelineSpans,rt as wallLength,it as weldShortWalls,Nt as worldTolerances};
|
|
1
|
+
"use client";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{useLabels as r}from"./common/configProvider/useLabels.mjs";import{usePresentationDefault as i}from"./common/configProvider/usePresentationDefault.mjs";import{Presentation as a}from"./common/configProvider/presentation.types.mjs";import o from"./common/accordion/accordion.mjs";import s from"./common/loading/spinnerLoading/index.mjs";import{ButtonSize as c,ButtonStyleType as l,ButtonType as u}from"./common/button/button.types.mjs";import d from"./common/ripple/ripple.mjs";import f from"./common/button/button.mjs";import p from"./common/actionButtons/actionButtons.mjs";import m from"./common/interactableDiv/index.mjs";import h from"./common/actionIcon/actionIcon.mjs";import g from"./common/scrollbarProvider/index.mjs";import{defaultTheme as _}from"./common/themeProvider/defaultTheme.mjs";import v from"./common/themeProvider/themeProvider.mjs";import{lightTheme as y}from"./common/themeProvider/lightTheme.mjs";import b from"./common/bodyEnd/bodyEnd.mjs";import x from"./common/hooks/useMediaQuery.mjs";import S from"./common/hooks/useCoarsePointer.mjs";import{useSwipeDismiss as C}from"./common/hooks/useSwipeDismiss.mjs";import{showToast as w}from"./common/toast/toastService.mjs";import T from"./common/ahroweProvider/ahroweProvider.mjs";import{AlertStyleType as E}from"./common/alert/alert.types.mjs";import D from"./common/alert/alert.mjs";import O from"./common/animatedLogo/animatedLogo.mjs";import{AnimatedTextUnit as k,AnimatedTextVariant as A}from"./common/animatedText/animatedText.types.mjs";import j from"./common/animatedText/animatedText.mjs";import{BadgePosition as M,BadgeStyleType as N}from"./common/badge/badge.types.mjs";import P from"./common/badge/badge.mjs";import F from"./common/avatar/avatar.mjs";import I from"./common/avatar/avatarGroup.mjs";import{PopoverAlign as L,PopoverPlacement as R,PopoverTrigger as z}from"./common/popover/popover.types.mjs";import{tabbablesIn as B}from"./common/hooks/useFocusBoundary.mjs";import{useVisualViewportSize as V}from"./common/hooks/useVisualViewportSize.mjs";import{useOverlay as H}from"./common/hooks/useOverlay.mjs";import U from"./common/popover/popover.mjs";import W from"./common/breadcrumb/breadcrumb.mjs";import{ButtonGroupOrientation as G}from"./common/buttonGroup/buttonGroup.types.mjs";import K from"./common/buttonGroup/buttonGroup.mjs";import{dateToDay as q,dateToTime as J,dayTimeToDate as Y,dayToDate as X}from"./common/utils/day.mjs";import{CalendarView as Z}from"./common/calendar/calendar.types.mjs";import Q from"./common/optionPicker/optionPicker.mjs";import $ from"./common/calendar/calendar.mjs";import{CardStyleType as ee}from"./common/card/card.types.mjs";import te from"./common/card/Card.mjs";import ne from"./common/card/CardHeader.mjs";import re from"./common/card/CardMedia.mjs";import ie from"./common/card/CardContent.mjs";import ae from"./common/card/CardActions.mjs";import oe from"./common/carousel/carousel.mjs";import se from"./common/checkbox/checkbox.mjs";import{ChipStyleType as ce}from"./common/chip/chip.types.mjs";import le from"./common/chip/chip.mjs";import ue from"./common/chip/chipContainer.mjs";import de from"./common/tooltip/tooltip.mjs";import{InputIconPosition as fe,InputType as pe}from"./common/input/input.types.mjs";import me from"./common/input/input.mjs";import he from"./common/colorPicker/colorPicker.mjs";import{useScrollEdges as ge}from"./common/hooks/useScrollEdges.mjs";import _e from"./common/modal/modal.mjs";import ve,{formatHotkey as ye}from"./common/hooks/useHotkeys.mjs";import{isMenuAction as be,isMenuHeading as xe,isMenuSeparator as Se}from"./common/menu/menu.types.mjs";import Ce from"./common/commandPalette/commandPalette.mjs";import we from"./common/confirmModal/confirmModal.mjs";import Te from"./common/hooks/useClipboard.mjs";import Ee from"./common/copyButton/copyButton.mjs";import{getLocale as De,mapLocale as Oe,setLocale as ke}from"./services/localization.mjs";import Ae from"./common/dropdown/dropdown.mjs";import je from"./common/datePicker/datePicker.mjs";import{DividerOrientation as Me,DividerTextPosition as Ne}from"./common/divider/divider.types.mjs";import Pe from"./common/divider/divider.mjs";import Fe from"./common/drawer/drawer.mjs";import{DropZoneReturnType as Ie,DropZoneStatus as Le}from"./common/dropZone/dropZone.types.mjs";import Re from"./common/dropZone/dropZone.mjs";import ze from"./common/emptyState/emptyState.mjs";import Be from"./common/errorBoundary/errorBoundary.mjs";import Ve from"./common/fab/fab.mjs";import He from"./common/flip/flip.mjs";import{DoorSwing as Ue,OpeningKind as We,PlanIssueKind as Ge,PlanUnitSystem as Ke,WallType as qe}from"./common/floorPlan/floorPlan.types.mjs";import{MIN_OPENING_WIDTH as Je,MIN_WALL_LENGTH as Ye}from"./common/floorPlan/floorPlan.geometry.mjs";import{DEFAULT_WALL_ATTRS as Xe,addOpening as Ze,addRect as Qe,addWall as $e,cleanupPlan as et,detachWall as tt,dissolveNode as nt,mergeNodes as rt,moveNode as it,removeOpening as at,removeWall as ot,scalePlan as st,splitWall as ct,transformPlan as lt,updateOpening as ut,validatePlan as dt,wallLength as ft,weldShortWalls as pt}from"./common/floorPlan/floorPlan.graph.mjs";import{MIN_FLOOR_HEIGHT as mt,addFloor as ht,duplicateFloor as gt,emptyFloor as _t,emptyFloorPlan as vt,floorBelow as yt,floorBounds as bt,floorIndex as xt,getFloor as St,moveFloor as Ct,removeFloor as wt,renameFloor as Tt,setFloor as Et,setFloorHeight as Dt,updateFloor as Ot}from"./common/floorPlan/floorPlan.plan.mjs";import{deriveFaces as kt,nodeDegrees as At}from"./common/floorPlan/floorPlan.faces.mjs";import{commitDerivation as jt,derivePlan as Mt,pruneUnmatchedRooms as Nt,roomAtPoint as Pt}from"./common/floorPlan/floorPlan.rooms.mjs";import{buildWallPaths as Ft,openingGeometry as It,wallCentrelineSpans as Lt}from"./common/floorPlan/floorPlan.path.mjs";import{HIT_PX as Rt,HIT_PX_COARSE as zt,hitTest as Bt,selectionsEqual as Vt,worldTolerances as Ht}from"./common/floorPlan/floorPlan.hit.mjs";import{DEFAULT_SNAP_OPTIONS as Ut,SnapKind as Wt,clientToWorld as Gt,resolveSnap as Kt,screenScale as qt}from"./common/floorPlan/floorPlan.snap.mjs";import{PLAN_FORMAT_VERSION as Jt,planFromJson as Yt,planToJson as Xt}from"./common/floorPlan/floorPlan.json.mjs";import{buildPlanMesh as Zt}from"./common/floorPlan/floorPlan.mesh.mjs";import{planFromLegacySvg as Qt}from"./common/floorPlan/legacySvg.mjs";import $t from"./common/iconPicker/iconPicker.mjs";import en from"./common/idleManager/idleManager.mjs";import tn from"./common/inputDropdown/inputDropdown.mjs";import nn from"./common/kanbanBoard/KanbanColumn.mjs";import rn from"./common/kanbanBoard/KanbanBoard.mjs";import an from"./common/searchInput/searchInput.mjs";import on from"./common/klipyPicker/klipyPicker.mjs";import sn from"./common/menu/menu.mjs";import{menuHotkeys as cn}from"./common/menu/menuHotkeys.mjs";import ln from"./common/multiSelect/multiSelect.mjs";import un from"./common/numberInput/index.mjs";import{OtpInputCharset as dn}from"./common/otpInput/otpInput.types.mjs";import fn from"./common/otpInput/otpInput.mjs";import pn from"./common/overscroll/overscroll.mjs";import mn from"./common/pagination/pagination.mjs";import hn from"./common/progressBar/progressBar.mjs";import{RadioGroupOrientation as gn}from"./common/radioGroup/radioGroup.types.mjs";import _n from"./common/radioGroup/radioGroup.mjs";import vn from"./common/rating/rating.mjs";import yn from"./common/revealLens/revealLens.mjs";import bn from"./common/roomDrawer/roomDrawer.mjs";import xn from"./common/roomViewer/roomViewer.mjs";import{ScrollFadeAxis as Sn}from"./common/scrollFade/scrollFade.types.mjs";import Cn from"./common/scrollFade/scrollFade.mjs";import{SectionHeaderSize as wn}from"./common/sectionHeader/sectionHeader.types.mjs";import Tn from"./common/sectionHeader/sectionHeader.mjs";import{SkeletonAnimation as En,SkeletonVariant as Dn}from"./common/skeleton/skeleton.types.mjs";import On from"./common/skeleton/skeleton.mjs";import kn from"./common/slider/slider.mjs";import An from"./common/splitButton/splitButton.mjs";import{StepperAlignment as jn,StepperCollapse as Mn,StepperLabelPlacement as Nn,StepperStyleType as Pn}from"./common/stepper/stepper.types.mjs";import Fn from"./common/stepper/stepper.mjs";import In from"./common/sticky/sticky.mjs";import Ln from"./common/switch/switch.mjs";import Rn from"./common/tabHeader/tabHeader.mjs";import zn from"./common/textarea/textarea.mjs";import{useTheme as Bn}from"./common/themeProvider/useTheme.mjs";import Vn,{TiltGroupContext as Hn,useTiltGroup as Un}from"./common/tiltGroup/tiltGroup.mjs";import{defaultTiltEasing as Wn}from"./common/tilt/tiltMath.mjs";import Gn from"./common/tilt/tilt.mjs";import Kn from"./common/timeInput/timeInput.mjs";import{TimelineAlignment as qn,TimelineItemStatus as Jn}from"./common/timeline/timeline.types.mjs";import Yn from"./common/timeline/timeline.mjs";import Xn from"./common/timer/timer.mjs";import Zn from"./common/virtualList/virtualList.mjs";import{flattenTree as Qn}from"./common/tree/flattenTree.mjs";import $n from"./common/tree/tree.mjs";import{WeatherType as er}from"./common/weatherIcon/weatherIcon.types.mjs";import tr from"./common/weatherIcon/weatherIcon.mjs";import nr from"./common/wizard/wizard.mjs";import rr from"./services/formValidation/FormValidatorGroupWithForm.mjs";import ir from"./services/formValidation/validatableComponent.mjs";import{useFormValidatorGroup as ar}from"./services/formValidation/useFormValidatorGroup.mjs";import{FormValidator as or,Validators as sr,useFormValidator as cr}from"./services/formValidation/index.mjs";import{hasEightPasswordChars as lr,hasOnePasswordDigit as ur,hasOnePasswordLetter as dr,isBic as fr,isDate as pr,isDay as mr,isEmail as hr,isISODate as gr,isNumber as _r,isPassword as vr,isURL as yr}from"@ahrowe/form-validation";export{o as Accordion,e as AccordionStyleType,p as ActionButtons,h as ActionIcon,T as AhroweProvider,D as Alert,E as AlertStyleType,O as AnimatedLogo,j as AnimatedText,k as AnimatedTextUnit,A as AnimatedTextVariant,F as Avatar,I as AvatarGroup,P as Badge,M as BadgePosition,N as BadgeStyleType,b as BodyEnd,W as Breadcrumb,f as Button,K as ButtonGroup,G as ButtonGroupOrientation,c as ButtonSize,l as ButtonStyleType,u as ButtonType,$ as Calendar,Z as CalendarView,te as Card,ae as CardActions,ie as CardContent,ne as CardHeader,re as CardMedia,ee as CardStyleType,oe as Carousel,se as Checkbox,le as Chip,ue as ChipContainer,ce as ChipStyleType,he as ColorPicker,Ce as CommandPalette,t as ConfigProvider,we as ConfirmModal,Ee as CopyButton,Ut as DEFAULT_SNAP_OPTIONS,Xe as DEFAULT_WALL_ATTRS,je as DatePicker,Pe as Divider,Me as DividerOrientation,Ne as DividerTextPosition,Ue as DoorSwing,Fe as Drawer,Re as DropZone,Ie as DropZoneReturnType,Le as DropZoneStatus,Ae as Dropdown,ze as EmptyState,Be as ErrorBoundary,Ve as Fab,He as Flip,or as FormValidator,rr as FormValidatorGroup,Rt as HIT_PX,zt as HIT_PX_COARSE,$t as IconPicker,en as IdleManager,me as Input,tn as InputDropdown,fe as InputIconPosition,pe as InputType,m as InteractableDiv,rn as KanbanBoard,nn as KanbanColumn,on as KlipyPicker,mt as MIN_FLOOR_HEIGHT,Je as MIN_OPENING_WIDTH,Ye as MIN_WALL_LENGTH,sn as Menu,_e as Modal,ln as MultiSelect,un as NumberInput,We as OpeningKind,Q as OptionPicker,fn as OtpInput,dn as OtpInputCharset,pn as Overscroll,Jt as PLAN_FORMAT_VERSION,mn as Pagination,Ge as PlanIssueKind,Ke as PlanUnitSystem,U as Popover,L as PopoverAlign,R as PopoverPlacement,z as PopoverTrigger,a as Presentation,hn as ProgressBar,_n as RadioGroup,gn as RadioGroupOrientation,vn as Rating,yn as RevealLens,d as Ripple,bn as RoomDrawer,xn as RoomViewer,Cn as ScrollFade,Sn as ScrollFadeAxis,g as ScrollbarProvider,an as SearchInput,Tn as SectionHeader,wn as SectionHeaderSize,On as Skeleton,En as SkeletonAnimation,Dn as SkeletonVariant,kn as Slider,Wt as SnapKind,s as SpinnerLoading,An as SplitButton,Fn as Stepper,jn as StepperAlignment,Mn as StepperCollapse,Nn as StepperLabelPlacement,Pn as StepperStyleType,In as Sticky,Ln as Switch,Rn as TabHeader,zn as Textarea,v as ThemeProvider,Gn as Tilt,Vn as TiltGroup,Hn as TiltGroupContext,Kn as TimeInput,Yn as Timeline,qn as TimelineAlignment,Jn as TimelineItemStatus,Xn as Timer,de as Tooltip,$n as Tree,ir as ValidatableComponent,sr as Validators,Zn as VirtualList,qe as WallType,tr as WeatherIcon,er as WeatherType,nr as Wizard,ht as addFloor,Ze as addOpening,Qe as addRect,$e as addWall,Zt as buildPlanMesh,Ft as buildWallPaths,et as cleanupPlan,Gt as clientToWorld,jt as commitDerivation,q as dateToDay,J as dateToTime,Y as dayTimeToDate,X as dayToDate,_ as defaultTheme,Wn as defaultTiltEasing,kt as deriveFaces,Mt as derivePlan,tt as detachWall,nt as dissolveNode,gt as duplicateFloor,_t as emptyFloor,vt as emptyFloorPlan,Qn as flattenTree,yt as floorBelow,bt as floorBounds,xt as floorIndex,ye as formatHotkey,St as getFloor,De as getLocale,lr as hasEightPasswordChars,ur as hasOnePasswordDigit,dr as hasOnePasswordLetter,Bt as hitTest,fr as isBic,pr as isDate,mr as isDay,hr as isEmail,gr as isISODate,be as isMenuAction,xe as isMenuHeading,Se as isMenuSeparator,_r as isNumber,vr as isPassword,yr as isURL,y as lightTheme,Oe as mapLocale,cn as menuHotkeys,rt as mergeNodes,Ct as moveFloor,it as moveNode,At as nodeDegrees,It as openingGeometry,Yt as planFromJson,Qt as planFromLegacySvg,Xt as planToJson,Nt as pruneUnmatchedRooms,wt as removeFloor,at as removeOpening,ot as removeWall,Tt as renameFloor,Kt as resolveSnap,Pt as roomAtPoint,st as scalePlan,qt as screenScale,Vt as selectionsEqual,Et as setFloor,Dt as setFloorHeight,ke as setLocale,w as showToast,ct as splitWall,B as tabbablesIn,lt as transformPlan,Ot as updateFloor,ut as updateOpening,Te as useClipboard,S as useCoarsePointer,n as useComponentDefaults,cr as useFormValidator,ar as useFormValidatorGroup,ve as useHotkeys,r as useLabels,x as useMediaQuery,H as useOverlay,i as usePresentationDefault,ge as useScrollEdges,C as useSwipeDismiss,Bn as useTheme,Un as useTiltGroup,V as useVisualViewportSize,dt as validatePlan,Lt as wallCentrelineSpans,ft as wallLength,pt as weldShortWalls,Ht as worldTolerances};
|