@ahrowe/ui 0.37.0 → 0.39.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 +5 -2
- package/dist/cjs-types/common/commandPalette/commandPalette.d.ts +4 -0
- package/dist/cjs-types/common/commandPalette/commandPalette.types.d.ts +42 -0
- package/dist/cjs-types/common/commandPalette/filterCommands.d.ts +15 -0
- package/dist/cjs-types/common/commandPalette/index.d.ts +2 -0
- package/dist/cjs-types/common/configProvider/configProvider.types.d.ts +6 -0
- package/dist/cjs-types/common/copyButton/copyButton.d.ts +4 -0
- package/dist/cjs-types/common/copyButton/copyButton.types.d.ts +36 -0
- package/dist/cjs-types/common/copyButton/index.d.ts +2 -0
- package/dist/cjs-types/common/datePicker/components/datePickerMonth/datePickerMonth.types.d.ts +6 -6
- package/dist/cjs-types/common/datePicker/dateFunctions.d.ts +10 -19
- package/dist/cjs-types/common/datePicker/datePicker.types.d.ts +20 -14
- package/dist/cjs-types/common/datePicker/index.d.ts +1 -0
- package/dist/cjs-types/common/errorBoundary/errorBoundary.d.ts +0 -3
- package/dist/cjs-types/common/errorBoundary/errorBoundary.types.d.ts +2 -3
- package/dist/cjs-types/common/hooks/index.d.ts +2 -0
- package/dist/cjs-types/common/hooks/useClipboard.d.ts +16 -0
- package/dist/cjs-types/common/inputDropdown/inputDropdown.types.d.ts +7 -1
- package/dist/cjs-types/common/menu/menu.types.d.ts +2 -0
- package/dist/cjs-types/common/popover/popover.types.d.ts +5 -0
- package/dist/cjs-types/common/themeProvider/themeProvider.d.ts +8 -7
- package/dist/cjs-types/common/utils/day.d.ts +16 -0
- package/dist/cjs-types/common/weatherIcon/index.d.ts +3 -0
- package/dist/cjs-types/common/weatherIcon/parts.d.ts +26 -0
- package/dist/cjs-types/common/weatherIcon/weatherIcon.d.ts +4 -0
- package/dist/cjs-types/common/weatherIcon/weatherIcon.types.d.ts +44 -0
- package/dist/cjs-types/index.d.ts +7 -1
- package/dist/esm/common/buttonGroup/buttonGroup.module.mjs.map +1 -1
- package/dist/esm/common/commandPalette/commandPalette.mjs +2 -0
- package/dist/esm/common/commandPalette/commandPalette.mjs.map +1 -0
- package/dist/esm/common/commandPalette/commandPalette.module.mjs +2 -0
- package/dist/esm/common/commandPalette/commandPalette.module.mjs.map +1 -0
- package/dist/esm/common/commandPalette/filterCommands.mjs +2 -0
- package/dist/esm/common/commandPalette/filterCommands.mjs.map +1 -0
- package/dist/esm/common/copyButton/copyButton.mjs +2 -0
- package/dist/esm/common/copyButton/copyButton.mjs.map +1 -0
- package/dist/esm/common/copyButton/copyButton.module.mjs +2 -0
- package/dist/esm/common/copyButton/copyButton.module.mjs.map +1 -0
- package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs +1 -1
- package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs.map +1 -1
- package/dist/esm/common/datePicker/dateFunctions.mjs +1 -1
- package/dist/esm/common/datePicker/dateFunctions.mjs.map +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs.map +1 -1
- package/dist/esm/common/errorBoundary/errorBoundary.mjs +2 -2
- package/dist/esm/common/errorBoundary/errorBoundary.mjs.map +1 -1
- package/dist/esm/common/errorBoundary/errorBoundary.module.mjs +1 -1
- package/dist/esm/common/errorBoundary/errorBoundary.module.mjs.map +1 -1
- package/dist/esm/common/hooks/useClipboard.mjs +2 -0
- package/dist/esm/common/hooks/useClipboard.mjs.map +1 -0
- package/dist/esm/common/hooks/useFocusBoundary.mjs +1 -1
- package/dist/esm/common/hooks/useFocusBoundary.mjs.map +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.mjs +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.mjs.map +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.module.mjs +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.module.mjs.map +1 -1
- package/dist/esm/common/menu/menu.mjs +1 -1
- package/dist/esm/common/menu/menu.mjs.map +1 -1
- package/dist/esm/common/menu/menu.types.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/popover/popover.types.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/timer/timer.mjs +1 -1
- package/dist/esm/common/timer/timer.mjs.map +1 -1
- package/dist/esm/common/utils/day.mjs +2 -0
- package/dist/esm/common/utils/day.mjs.map +1 -0
- package/dist/esm/common/weatherIcon/parts.mjs +2 -0
- package/dist/esm/common/weatherIcon/parts.mjs.map +1 -0
- package/dist/esm/common/weatherIcon/weatherIcon.mjs +2 -0
- package/dist/esm/common/weatherIcon/weatherIcon.mjs.map +1 -0
- package/dist/esm/common/weatherIcon/weatherIcon.module.mjs +2 -0
- package/dist/esm/common/weatherIcon/weatherIcon.module.mjs.map +1 -0
- package/dist/esm/common/weatherIcon/weatherIcon.types.mjs +2 -0
- package/dist/esm/common/weatherIcon/weatherIcon.types.mjs.map +1 -0
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/common/commandPalette/commandPalette.d.ts +4 -0
- package/dist/types/common/commandPalette/commandPalette.types.d.ts +42 -0
- package/dist/types/common/commandPalette/filterCommands.d.ts +15 -0
- package/dist/types/common/commandPalette/index.d.ts +2 -0
- package/dist/types/common/configProvider/configProvider.types.d.ts +6 -0
- package/dist/types/common/copyButton/copyButton.d.ts +4 -0
- package/dist/types/common/copyButton/copyButton.types.d.ts +36 -0
- package/dist/types/common/copyButton/index.d.ts +2 -0
- package/dist/types/common/datePicker/components/datePickerMonth/datePickerMonth.types.d.ts +6 -6
- package/dist/types/common/datePicker/dateFunctions.d.ts +10 -19
- package/dist/types/common/datePicker/datePicker.types.d.ts +20 -14
- package/dist/types/common/datePicker/index.d.ts +1 -0
- package/dist/types/common/errorBoundary/errorBoundary.d.ts +0 -3
- package/dist/types/common/errorBoundary/errorBoundary.types.d.ts +2 -3
- package/dist/types/common/hooks/index.d.ts +2 -0
- package/dist/types/common/hooks/useClipboard.d.ts +16 -0
- package/dist/types/common/inputDropdown/inputDropdown.types.d.ts +7 -1
- package/dist/types/common/menu/menu.types.d.ts +2 -0
- package/dist/types/common/popover/popover.types.d.ts +5 -0
- package/dist/types/common/themeProvider/themeProvider.d.ts +8 -7
- package/dist/types/common/utils/day.d.ts +16 -0
- package/dist/types/common/weatherIcon/index.d.ts +3 -0
- package/dist/types/common/weatherIcon/parts.d.ts +26 -0
- package/dist/types/common/weatherIcon/weatherIcon.d.ts +4 -0
- package/dist/types/common/weatherIcon/weatherIcon.types.d.ts +44 -0
- package/dist/types/index.d.ts +7 -1
- package/docs/ButtonGroup.md +2 -0
- package/docs/CLAUDE.md +9 -2
- package/docs/CommandPalette.md +84 -0
- package/docs/ConfigProvider.md +2 -2
- package/docs/CopyButton.md +45 -0
- package/docs/DatePicker.md +72 -45
- package/docs/ErrorBoundary.md +4 -4
- package/docs/Fab.md +1 -2
- package/docs/FormValidator.md +3 -3
- package/docs/Hooks.md +39 -3
- package/docs/InputDropdown.md +9 -4
- package/docs/Menu.md +5 -3
- package/docs/Popover.md +15 -0
- package/docs/WeatherIcon.md +49 -0
- package/package.json +2 -3
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{renderIcon as n}from"../utils/renderIcon.mjs";import r from"../modal/modal.mjs";import{formatHotkey as ee}from"../hooks/useHotkeys.mjs";import{edgeIndex as i,nextIndex as a,scrollOptionIntoView as o}from"../utils/listNavigation.mjs";import{filterCommands as s,groupCommands as c}from"./filterCommands.mjs";import l from"./commandPalette.module.mjs";import{useEffect as u,useId as te,useRef as d,useState as f}from"react";import p from"classnames";import{faMagnifyingGlass as m}from"@fortawesome/free-solid-svg-icons";import{jsx as h,jsxs as g}from"react/jsx-runtime";var _={label:`Search commands`,placeholder:`Type a command or search…`,empty:`No results`,loading:`Searching…`,results:e=>e===1?`1 result`:`${e} results`};function v(v){let{items:y,isOpen:b,onClose:x,onAction:S,onQueryChange:C,filter:w=!0,isLoading:T=!1,presentation:E,labels:D,className:O,style:k,classNames:A,styles:j,...ne}=e(`CommandPalette`,v),M=t(`CommandPalette`,D,_),N=te(),P=d(null),[F,I]=f(``),[L,R]=f(null),[z,B]=f(b);b!==z&&(B(b),b&&(I(``),R(null)));let V=d(C);u(()=>{V.current=C}),u(()=>{b&&V.current?.(``)},[b]);let H=w?s(c(y),F):c(y),U=H.flatMap(e=>e.actions),W=e=>!!U[e]?.disabled,G=U.findIndex(e=>e.id===L&&!e.disabled),K=G>=0?G:i(`first`,U.length,{isDisabled:W}),q=e=>`${N}-${encodeURIComponent(e.id)}`,J=K===null?void 0:q(U[K]);u(()=>{J&&o(P.current,document.getElementById(J))},[J]);function Y(e){e&&!e.disabled&&(e.onClick?.(),S?.(e.id),x())}function X(e){if(!e.nativeEvent.isComposing){if(e.key===`ArrowDown`||e.key===`ArrowUp`){let t=a(K,e.key===`ArrowDown`?1:-1,U.length,{isDisabled:W});R(t===null?null:U[t].id)}else if(e.key===`Enter`)Y(K===null?void 0:U[K]);else return;e.preventDefault()}}let Z=F.trim()!==``,Q=T?M.loading:M.empty,$=-1;return g(r,{...ne,"aria-label":M.label,isOpen:b,onClose:x,hideHeader:!0,presentation:E,className:p(l.commandPalette,O,A?.root),style:{...k,...j?.root},children:[g(`div`,{className:p(l.commandPaletteSearch,A?.search),style:j?.search,children:[n(m,{className:l.commandPaletteSearchIcon}),h(`input`,{type:`text`,role:`combobox`,"aria-label":M.label,"aria-expanded":`true`,"aria-controls":N,"aria-autocomplete":`list`,"aria-activedescendant":J,autoComplete:`off`,spellCheck:!1,placeholder:M.placeholder,value:F,onChange:e=>{I(e.target.value),R(null),C?.(e.target.value)},onKeyDown:X,className:p(l.commandPaletteInput,A?.input),style:j?.input})]}),h(`div`,{ref:P,id:N,role:`listbox`,"aria-label":M.label,className:p(l.commandPaletteList,A?.list),style:j?.list,children:H.map((e,t)=>{let r=`${N}-heading-${t}`;return g(`div`,{role:e.heading===void 0?`presentation`:`group`,"aria-labelledby":e.heading===void 0?void 0:r,children:[e.separated&&t>0&&h(`div`,{"aria-hidden":!0,className:p(l.commandPaletteSeparator,A?.separator),style:j?.separator}),e.heading!==void 0&&h(`div`,{id:r,role:`presentation`,className:p(l.commandPaletteHeading,A?.heading),style:j?.heading,children:e.heading}),e.actions.map(e=>{$+=1;let t=$;return g(`div`,{id:q(e),role:`option`,"aria-selected":t===K,"aria-disabled":e.disabled||void 0,className:p(l.commandPaletteItem,t===K&&l.commandPaletteItemActive,e.danger&&l.commandPaletteItemDanger,e.disabled&&l.commandPaletteItemDisabled,A?.item),style:j?.item,onMouseDown:e=>e.preventDefault(),onMouseMove:()=>!e.disabled&&R(e.id),onClick:()=>Y(e),children:[e.icon!=null&&n(e.icon,{className:p(l.commandPaletteItemIcon,A?.itemIcon),style:j?.itemIcon}),h(`span`,{className:p(l.commandPaletteItemLabel,A?.itemLabel),style:j?.itemLabel,children:e.label}),e.shortcut!=null&&h(`span`,{className:p(l.commandPaletteItemShortcut,A?.itemShortcut),style:j?.itemShortcut,children:ee(e.shortcut)})]},e.id)})]},t)})}),Z&&U.length===0&&h(`div`,{className:p(l.commandPaletteEmpty,A?.empty),style:j?.empty,children:Q}),h(`span`,{className:l.commandPaletteStatus,role:`status`,"aria-live":`polite`,children:Z?U.length>0?M.results(U.length):Q:``})]})}export{v as default};
|
|
2
|
+
//# sourceMappingURL=commandPalette.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandPalette.mjs","names":[],"sources":["../../../../package/common/commandPalette/commandPalette.tsx"],"sourcesContent":["import { useEffect, useId, useRef, useState, type KeyboardEvent, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';\n\nimport Modal from '../modal';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport { formatHotkey } from '../hooks/useHotkeys';\nimport { edgeIndex, nextIndex, scrollOptionIntoView } from '../utils/listNavigation';\nimport { renderIcon } from '../utils/renderIcon';\nimport type { MenuAction } from '../menu/menu.types';\nimport { filterCommands, groupCommands } from './filterCommands';\nimport type { CommandPaletteLabels, CommandPaletteProps } from './commandPalette.types';\nimport styles from './commandPalette.module.pcss';\n\nconst DEFAULT_LABELS: Required<CommandPaletteLabels> = {\n label: 'Search commands',\n placeholder: 'Type a command or search…',\n empty: 'No results',\n loading: 'Searching…',\n results: (count) => (count === 1 ? '1 result' : `${count} results`),\n};\n\nfunction CommandPalette(props: CommandPaletteProps): ReactElement {\n const {\n items,\n isOpen,\n onClose,\n onAction,\n onQueryChange,\n filter = true,\n isLoading = false,\n presentation,\n labels,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('CommandPalette', props);\n const text = useLabels('CommandPalette', labels, DEFAULT_LABELS);\n const listId = useId();\n const listRef = useRef<HTMLDivElement>(null);\n\n const [query, setQuery] = useState('');\n // An id rather than an index, so the highlight stays on the same command while server results\n // are replaced around it. Typing clears it instead, so Enter runs the best match.\n const [activeId, setActiveId] = useState<string | null>(null);\n const [wasOpen, setWasOpen] = useState(isOpen);\n if (isOpen !== wasOpen) {\n setWasOpen(isOpen);\n if (isOpen) {\n setQuery('');\n setActiveId(null);\n }\n }\n\n // Read through a ref so an inline handler does not re-fire the effect on every parent render.\n const onQueryChangeRef = useRef(onQueryChange);\n useEffect(() => {\n onQueryChangeRef.current = onQueryChange;\n });\n useEffect(() => {\n if (isOpen) onQueryChangeRef.current?.('');\n }, [isOpen]);\n\n const groups = filter ? filterCommands(groupCommands(items), query) : groupCommands(items);\n const actions = groups.flatMap((group) => group.actions);\n const isDisabled = (index: number) => !!actions[index]?.disabled;\n const found = actions.findIndex((action) => action.id === activeId && !action.disabled);\n const activeIndex = found >= 0 ? found : edgeIndex('first', actions.length, { isDisabled });\n // From the command's id, not its position: an id that stayed the same while the option under it\n // changed would not make a screen reader announce the new highlight.\n const optionId = (action: MenuAction) => `${listId}-${encodeURIComponent(action.id)}`;\n const activeOptionId = activeIndex === null ? undefined : optionId(actions[activeIndex]);\n\n useEffect(() => {\n if (!activeOptionId) return;\n scrollOptionIntoView(listRef.current, document.getElementById(activeOptionId));\n }, [activeOptionId]);\n\n function run(action: MenuAction | undefined) {\n if (!action || action.disabled) return;\n action.onClick?.();\n onAction?.(action.id);\n onClose();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLInputElement>) {\n // Enter confirms an IME composition before it means anything here.\n if (event.nativeEvent.isComposing) return;\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n const next = nextIndex(activeIndex, event.key === 'ArrowDown' ? 1 : -1, actions.length, { isDisabled });\n setActiveId(next === null ? null : actions[next].id);\n } else if (event.key === 'Enter') {\n run(activeIndex === null ? undefined : actions[activeIndex]);\n } else {\n return;\n }\n event.preventDefault();\n }\n\n const hasQuery = query.trim() !== '';\n const emptyText = isLoading ? text.loading : text.empty;\n let index = -1;\n\n return (\n <Modal\n {...rest}\n aria-label={text.label}\n isOpen={isOpen}\n onClose={onClose}\n hideHeader\n presentation={presentation}\n className={cx(styles.commandPalette, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div className={cx(styles.commandPaletteSearch, classNames?.search)} style={slotStyles?.search}>\n {renderIcon(faMagnifyingGlass, { className: styles.commandPaletteSearchIcon })}\n <input\n type='text'\n role='combobox'\n aria-label={text.label}\n aria-expanded='true'\n aria-controls={listId}\n aria-autocomplete='list'\n aria-activedescendant={activeOptionId}\n autoComplete='off'\n spellCheck={false}\n placeholder={text.placeholder}\n value={query}\n onChange={(event) => {\n setQuery(event.target.value);\n setActiveId(null);\n onQueryChange?.(event.target.value);\n }}\n onKeyDown={handleKeyDown}\n className={cx(styles.commandPaletteInput, classNames?.input)}\n style={slotStyles?.input}\n />\n </div>\n\n <div\n ref={listRef}\n id={listId}\n role='listbox'\n aria-label={text.label}\n className={cx(styles.commandPaletteList, classNames?.list)}\n style={slotStyles?.list}\n >\n {groups.map((group, groupIndex) => {\n const headingId = `${listId}-heading-${groupIndex}`;\n return (\n <div\n // Groups carry no id of their own; a new query re-renders the list wholesale anyway.\n key={groupIndex}\n role={group.heading === undefined ? 'presentation' : 'group'}\n aria-labelledby={group.heading === undefined ? undefined : headingId}\n >\n {group.separated && groupIndex > 0 && (\n <div\n aria-hidden\n className={cx(styles.commandPaletteSeparator, classNames?.separator)}\n style={slotStyles?.separator}\n />\n )}\n {group.heading !== undefined && (\n <div\n id={headingId}\n role='presentation'\n className={cx(styles.commandPaletteHeading, classNames?.heading)}\n style={slotStyles?.heading}\n >\n {group.heading}\n </div>\n )}\n {group.actions.map((action) => {\n index += 1;\n const own = index;\n return (\n <div\n key={action.id}\n id={optionId(action)}\n role='option'\n aria-selected={own === activeIndex}\n aria-disabled={action.disabled || undefined}\n className={cx(\n styles.commandPaletteItem,\n own === activeIndex && styles.commandPaletteItemActive,\n action.danger && styles.commandPaletteItemDanger,\n action.disabled && styles.commandPaletteItemDisabled,\n classNames?.item,\n )}\n style={slotStyles?.item}\n // Keeps the focus, and so the caret, in the search field.\n onMouseDown={(event) => event.preventDefault()}\n // Move, not enter: a list scrolling under a resting pointer must not steal the highlight.\n onMouseMove={() => !action.disabled && setActiveId(action.id)}\n onClick={() => run(action)}\n >\n {action.icon != null &&\n renderIcon(action.icon, {\n className: cx(styles.commandPaletteItemIcon, classNames?.itemIcon),\n style: slotStyles?.itemIcon,\n })}\n <span\n className={cx(styles.commandPaletteItemLabel, classNames?.itemLabel)}\n style={slotStyles?.itemLabel}\n >\n {action.label}\n </span>\n {action.shortcut != null && (\n <span\n className={cx(styles.commandPaletteItemShortcut, classNames?.itemShortcut)}\n style={slotStyles?.itemShortcut}\n >\n {formatHotkey(action.shortcut)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n })}\n </div>\n\n {hasQuery && actions.length === 0 && (\n <div className={cx(styles.commandPaletteEmpty, classNames?.empty)} style={slotStyles?.empty}>\n {emptyText}\n </div>\n )}\n <span className={styles.commandPaletteStatus} role='status' aria-live='polite'>\n {hasQuery ? (actions.length > 0 ? text.results(actions.length) : emptyText) : ''}\n </span>\n </Modal>\n );\n}\n\nexport default CommandPalette;\n"],"mappings":"ytBAcA,IAAM,EAAiD,CACrD,MAAO,kBACP,YAAa,4BACb,MAAO,aACP,QAAS,aACT,QAAU,GAAW,IAAU,EAAI,WAAa,GAAG,EAAM,SAC3D,EAEA,SAAS,EAAe,EAA0C,CAChE,GAAM,CACJ,QACA,SACA,UACA,WACA,gBACA,SAAS,GACT,YAAY,GACZ,eACA,SACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,IACD,EAAqB,iBAAkB,CAAK,EAC1C,EAAO,EAAU,iBAAkB,EAAQ,CAAc,EACzD,EAAS,GAAM,EACf,EAAU,EAAuB,IAAI,EAErC,CAAC,EAAO,GAAY,EAAS,EAAE,EAG/B,CAAC,EAAU,GAAe,EAAwB,IAAI,EACtD,CAAC,EAAS,GAAc,EAAS,CAAM,EACzC,IAAW,IACb,EAAW,CAAM,EACb,IACF,EAAS,EAAE,EACX,EAAY,IAAI,IAKpB,IAAM,EAAmB,EAAO,CAAa,EAC7C,MAAgB,CACd,EAAiB,QAAU,CAC7B,CAAC,EACD,MAAgB,CACV,GAAQ,EAAiB,UAAU,EAAE,CAC3C,EAAG,CAAC,CAAM,CAAC,EAEX,IAAM,EAAS,EAAS,EAAe,EAAc,CAAK,EAAG,CAAK,EAAI,EAAc,CAAK,EACnF,EAAU,EAAO,QAAS,GAAU,EAAM,OAAO,EACjD,EAAc,GAAkB,CAAC,CAAC,EAAQ,EAAM,EAAE,SAClD,EAAQ,EAAQ,UAAW,GAAW,EAAO,KAAO,GAAY,CAAC,EAAO,QAAQ,EAChF,EAAc,GAAS,EAAI,EAAQ,EAAU,QAAS,EAAQ,OAAQ,CAAE,YAAW,CAAC,EAGpF,EAAY,GAAuB,GAAG,EAAO,GAAG,mBAAmB,EAAO,EAAE,IAC5E,EAAiB,IAAgB,KAAO,IAAA,GAAY,EAAS,EAAQ,EAAY,EAEvF,MAAgB,CACT,GACL,EAAqB,EAAQ,QAAS,SAAS,eAAe,CAAc,CAAC,CAC/E,EAAG,CAAC,CAAc,CAAC,EAEnB,SAAS,EAAI,EAAgC,CACtC,GAAU,GAAO,WACtB,EAAO,UAAU,EACjB,IAAW,EAAO,EAAE,EACpB,EAAQ,EACV,CAEA,SAAS,EAAc,EAAwC,CAEzD,MAAM,YAAY,YACtB,IAAI,EAAM,MAAQ,aAAe,EAAM,MAAQ,UAAW,CACxD,IAAM,EAAO,EAAU,EAAa,EAAM,MAAQ,YAAc,EAAI,GAAI,EAAQ,OAAQ,CAAE,YAAW,CAAC,EACtG,EAAY,IAAS,KAAO,KAAO,EAAQ,EAAK,CAAC,EAAE,CACrD,MAAO,GAAI,EAAM,MAAQ,QACvB,EAAI,IAAgB,KAAO,IAAA,GAAY,EAAQ,EAAY,OAE3D,OAEF,EAAM,eAAe,CAFnB,CAGJ,CAEA,IAAM,EAAW,EAAM,KAAK,IAAM,GAC5B,EAAY,EAAY,EAAK,QAAU,EAAK,MAC9C,EAAQ,GAEZ,OACE,EAAC,EAAD,CACE,GAAI,GACJ,aAAY,EAAK,MACT,SACC,UACT,WAAA,GACc,eACd,UAAW,EAAG,EAAO,eAAgB,EAAW,GAAY,IAAI,EAChE,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EARzC,SAAA,CAUE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,qBAAsB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAxF,SAAA,CACG,EAAW,EAAmB,CAAE,UAAW,EAAO,wBAAyB,CAAC,EAC7E,EAAC,QAAD,CACE,KAAK,OACL,KAAK,WACL,aAAY,EAAK,MACjB,gBAAc,OACd,gBAAe,EACf,oBAAkB,OAClB,wBAAuB,EACvB,aAAa,MACb,WAAY,GACZ,YAAa,EAAK,YAClB,MAAO,EACP,SAAW,GAAU,CACnB,EAAS,EAAM,OAAO,KAAK,EAC3B,EAAY,IAAI,EAChB,IAAgB,EAAM,OAAO,KAAK,CACpC,EACA,UAAW,EACX,UAAW,EAAG,EAAO,oBAAqB,GAAY,KAAK,EAC3D,MAAO,GAAY,KACpB,CAAA,CACE,IAEL,EAAC,MAAD,CACE,IAAK,EACL,GAAI,EACJ,KAAK,UACL,aAAY,EAAK,MACjB,UAAW,EAAG,EAAO,mBAAoB,GAAY,IAAI,EACzD,MAAO,GAAY,KAElB,SAAA,EAAO,KAAK,EAAO,IAAe,CACjC,IAAM,EAAY,GAAG,EAAO,WAAW,IACvC,OACE,EAAC,MAAD,CAGE,KAAM,EAAM,UAAY,IAAA,GAAY,eAAiB,QACrD,kBAAiB,EAAM,UAAY,IAAA,GAAY,IAAA,GAAY,EAJ7D,SAAA,CAMG,EAAM,WAAa,EAAa,GAC/B,EAAC,MAAD,CACE,cAAA,GACA,UAAW,EAAG,EAAO,wBAAyB,GAAY,SAAS,EACnE,MAAO,GAAY,SACpB,CAAA,EAEF,EAAM,UAAY,IAAA,IACjB,EAAC,MAAD,CACE,GAAI,EACJ,KAAK,eACL,UAAW,EAAG,EAAO,sBAAuB,GAAY,OAAO,EAC/D,MAAO,GAAY,QAElB,SAAA,EAAM,OACJ,CAAA,EAEN,EAAM,QAAQ,IAAK,GAAW,CAC7B,GAAS,EACT,IAAM,EAAM,EACZ,OACE,EAAC,MAAD,CAEE,GAAI,EAAS,CAAM,EACnB,KAAK,SACL,gBAAe,IAAQ,EACvB,gBAAe,EAAO,UAAY,IAAA,GAClC,UAAW,EACT,EAAO,mBACP,IAAQ,GAAe,EAAO,yBAC9B,EAAO,QAAU,EAAO,yBACxB,EAAO,UAAY,EAAO,2BAC1B,GAAY,IACd,EACA,MAAO,GAAY,KAEnB,YAAc,GAAU,EAAM,eAAe,EAE7C,gBAAmB,CAAC,EAAO,UAAY,EAAY,EAAO,EAAE,EAC5D,YAAe,EAAI,CAAM,EAlB3B,SAAA,CAoBG,EAAO,MAAQ,MACd,EAAW,EAAO,KAAM,CACtB,UAAW,EAAG,EAAO,uBAAwB,GAAY,QAAQ,EACjE,MAAO,GAAY,QACrB,CAAC,EACH,EAAC,OAAD,CACE,UAAW,EAAG,EAAO,wBAAyB,GAAY,SAAS,EACnE,MAAO,GAAY,UAElB,SAAA,EAAO,KACJ,CAAA,EACL,EAAO,UAAY,MAClB,EAAC,OAAD,CACE,UAAW,EAAG,EAAO,2BAA4B,GAAY,YAAY,EACzE,MAAO,GAAY,aAElB,SAAA,GAAa,EAAO,QAAQ,CACzB,CAAA,CAEL,CAtCE,EAAA,EAAO,EAsCT,CAET,CAAC,CACE,CAnEE,EAAA,CAmEF,CAET,CAAC,CACE,CAAA,EAEJ,GAAY,EAAQ,SAAW,GAC9B,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,oBAAqB,GAAY,KAAK,EAAG,MAAO,GAAY,MACnF,SAAA,CACE,CAAA,EAEP,EAAC,OAAD,CAAM,UAAW,EAAO,qBAAsB,KAAK,SAAS,YAAU,SACnE,SAAA,EAAY,EAAQ,OAAS,EAAI,EAAK,QAAQ,EAAQ,MAAM,EAAI,EAAa,EAC1E,CAAA,CACD,GAEX"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";var e=`commandPalette_YtQdV`,t=`commandPalette-search_FII6k`,n=`commandPalette-search-icon_acfcm`,r=`commandPalette-input_Vb3da`,i=`commandPalette-list_93yGm`,a=`commandPalette-item_oa2PX`,o=`commandPalette-item-active_9KaV-`,s=`commandPalette-item-danger_VP4If`,c=`commandPalette-item-disabled_hiHzA`,l=`commandPalette-item-icon_N4L26`,u=`commandPalette-item-label_cy-ke`,d=`commandPalette-item-shortcut_G2KPh`,f=`commandPalette-heading_ONebI`,p=`commandPalette-separator_Yu8TJ`,m=`commandPalette-empty_LqVAt`,h=`commandPalette-status_rft-N`,g={commandPalette:e,"commandPalette-search":`commandPalette-search_FII6k`,commandPaletteSearch:t,"commandPalette-search-icon":`commandPalette-search-icon_acfcm`,commandPaletteSearchIcon:n,"commandPalette-input":`commandPalette-input_Vb3da`,commandPaletteInput:r,"commandPalette-list":`commandPalette-list_93yGm`,commandPaletteList:i,"commandPalette-item":`commandPalette-item_oa2PX`,commandPaletteItem:a,"commandPalette-item-active":`commandPalette-item-active_9KaV-`,commandPaletteItemActive:o,"commandPalette-item-danger":`commandPalette-item-danger_VP4If`,commandPaletteItemDanger:s,"commandPalette-item-disabled":`commandPalette-item-disabled_hiHzA`,commandPaletteItemDisabled:c,"commandPalette-item-icon":`commandPalette-item-icon_N4L26`,commandPaletteItemIcon:l,"commandPalette-item-label":`commandPalette-item-label_cy-ke`,commandPaletteItemLabel:u,"commandPalette-item-shortcut":`commandPalette-item-shortcut_G2KPh`,commandPaletteItemShortcut:d,"commandPalette-heading":`commandPalette-heading_ONebI`,commandPaletteHeading:f,"commandPalette-separator":`commandPalette-separator_Yu8TJ`,commandPaletteSeparator:p,"commandPalette-empty":`commandPalette-empty_LqVAt`,commandPaletteEmpty:m,"commandPalette-status":`commandPalette-status_rft-N`,commandPaletteStatus:h};export{e as commandPalette,m as commandPaletteEmpty,f as commandPaletteHeading,r as commandPaletteInput,a as commandPaletteItem,o as commandPaletteItemActive,s as commandPaletteItemDanger,c as commandPaletteItemDisabled,l as commandPaletteItemIcon,u as commandPaletteItemLabel,d as commandPaletteItemShortcut,i as commandPaletteList,t as commandPaletteSearch,n as commandPaletteSearchIcon,p as commandPaletteSeparator,h as commandPaletteStatus,g as default};
|
|
2
|
+
//# sourceMappingURL=commandPalette.module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandPalette.module.mjs","names":[],"sources":["../../../../package/common/commandPalette/commandPalette.module.pcss"],"sourcesContent":[".commandPalette {\n --modal-padding: var(--spacing-s);\n --modal-body-bleed: 0;\n\n width: 640px;\n\n /* Near the top rather than centred, so the panel does not jump as the list shrinks while\n typing. A sheet overrides both with its own doubled selector. */\n align-self: flex-start;\n margin-top: 12vh;\n\n &-search {\n display: flex;\n align-items: center;\n gap: var(--spacing-s);\n padding: var(--spacing-s) var(--spacing-m);\n border-bottom: 1px solid var(--border-color);\n\n &-icon {\n flex: none;\n color: var(--text-light);\n }\n }\n\n &-input {\n flex: 1;\n min-width: 0;\n padding: 4px 0;\n border: none;\n outline: none;\n background: transparent;\n font: inherit;\n font-size: 1.1em;\n color: var(--text-color);\n\n &::placeholder {\n color: var(--text-light);\n }\n }\n\n &-list {\n max-height: min(24rem, 60vh);\n max-height: min(24rem, 60dvh);\n overflow-y: auto;\n padding: 4px 0;\n\n &:empty {\n display: none;\n }\n }\n\n &-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n border-radius: var(--default-border-radius);\n color: var(--text-color);\n white-space: nowrap;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n /* Same token as Menu's highlight: `--background-accent-light` matches the modal surface in\n the default theme. */\n &-active {\n background: var(--background-accent);\n }\n\n &-danger {\n color: var(--error-color);\n }\n\n &-disabled {\n opacity: 0.45;\n cursor: default;\n }\n\n &-icon {\n flex: none;\n width: 1em;\n text-align: center;\n }\n\n &-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n &-shortcut {\n flex: none;\n margin-left: 16px;\n font-size: 0.85em;\n color: var(--text-light);\n }\n }\n\n &-heading {\n padding: 10px 12px 4px;\n font-size: 0.8em;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--text-light);\n }\n\n &-separator {\n height: 1px;\n margin: 4px 0;\n background: var(--border-color);\n }\n\n &-empty {\n padding: var(--spacing-l) var(--spacing-m);\n text-align: center;\n color: var(--text-light);\n }\n\n &-status {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n border: 0;\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{isMenuAction as e,isMenuHeading as t}from"../menu/menu.types.mjs";function n(e){return e.normalize(`NFD`).replace(/\p{Diacritic}/gu,``).toLowerCase()}function r(n){let r=[],i={separated:!1,actions:[]},a=()=>{(i.heading!==void 0||i.actions.length>0)&&r.push(i)};for(let r of n){if(e(r)){i.actions.push(r);continue}a(),i=t(r)?{heading:r.heading,separated:i.separated&&i.actions.length===0,actions:[]}:{separated:!0,actions:[]}}return a(),r.filter(e=>e.actions.length>0)}function i(e,t,r){let i=typeof e.label==`string`?n(e.label):``,a=(e.keywords??[]).map(n),o=[i,...a].join(` `);if(!t.every(e=>o.includes(e)))return null;if(i.startsWith(r))return 0;let s=e=>e.split(/\s+/).some(e=>e.startsWith(t[0]));return s(i)||a.some(s)?1:2}function a(e,t){let r=n(t.trim());if(!r)return e;let a=r.split(/\s+/);return e.map(e=>{let t=e.actions.map(e=>({action:e,rank:i(e,a,r)})).filter(e=>e.rank!==null).sort((e,t)=>e.rank-t.rank);return t.length===0?null:{group:{...e,separated:!1,actions:t.map(e=>e.action)},best:t[0].rank}}).filter(e=>e!==null).sort((e,t)=>e.best-t.best).map(e=>e.group)}export{a as filterCommands,r as groupCommands};
|
|
2
|
+
//# sourceMappingURL=filterCommands.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterCommands.mjs","names":[],"sources":["../../../../package/common/commandPalette/filterCommands.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { isMenuAction, isMenuHeading, type MenuAction, type MenuEntry } from '../menu/menu.types';\n\nexport interface CommandGroup {\n heading?: ReactNode;\n /** Whether a separator started this group, so the divider can be drawn above it. */\n separated: boolean;\n actions: MenuAction[];\n}\n\n// Lower-cased and stripped of accents, so \"uber\" finds \"Übersicht\".\nfunction normalize(text: string): string {\n return text\n .normalize('NFD')\n .replace(/\\p{Diacritic}/gu, '')\n .toLowerCase();\n}\n\n/** Splits entries into groups at each heading and separator, keeping their order. */\nexport function groupCommands(items: MenuEntry[]): CommandGroup[] {\n const groups: CommandGroup[] = [];\n let current: CommandGroup = { separated: false, actions: [] };\n const flush = () => {\n if (current.heading !== undefined || current.actions.length > 0) groups.push(current);\n };\n for (const entry of items) {\n if (isMenuAction(entry)) {\n current.actions.push(entry);\n continue;\n }\n flush();\n current = isMenuHeading(entry)\n ? { heading: entry.heading, separated: current.separated && current.actions.length === 0, actions: [] }\n : { separated: true, actions: [] };\n }\n flush();\n return groups.filter((group) => group.actions.length > 0);\n}\n\n/**\n * 0 when the label starts with the query, 1 when a word of the label or a keyword does, 2 for any\n * other match, `null` when a query word is missing from both the label and the keywords.\n *\n * A label that is not a string cannot be read, so such an action is found through its keywords only.\n */\nfunction rank(action: MenuAction, words: string[], query: string): number | null {\n const label = typeof action.label === 'string' ? normalize(action.label) : '';\n const keywords = (action.keywords ?? []).map(normalize);\n const haystack = [label, ...keywords].join(' ');\n if (!words.every((word) => haystack.includes(word))) return null;\n if (label.startsWith(query)) return 0;\n const hasWordStartingWith = (text: string) => text.split(/\\s+/).some((word) => word.startsWith(words[0]));\n if (hasWordStartingWith(label) || keywords.some(hasWordStartingWith)) return 1;\n return 2;\n}\n\ninterface RankedGroup {\n group: CommandGroup;\n best: number;\n}\n\n/**\n * The groups with only the actions matching `query`, best matches first within each group, and\n * the group holding the best match first. A heading moves with its group, never away from it.\n */\nexport function filterCommands(groups: CommandGroup[], query: string): CommandGroup[] {\n const normalized = normalize(query.trim());\n if (!normalized) return groups;\n const words = normalized.split(/\\s+/);\n\n // Both sorts rely on `Array.prototype.sort` being stable, so ties keep the order they were given in.\n return groups\n .map((group): RankedGroup | null => {\n const matches = group.actions\n .map((action) => ({ action, rank: rank(action, words, normalized) }))\n .filter((match): match is { action: MenuAction; rank: number } => match.rank !== null)\n .sort((a, b) => a.rank - b.rank);\n if (matches.length === 0) return null;\n return {\n // Separators are dropped while filtering: the headings still say where one group ends.\n group: { ...group, separated: false, actions: matches.map((match) => match.action) },\n best: matches[0].rank,\n };\n })\n .filter((ranked): ranked is RankedGroup => ranked !== null)\n .sort((a, b) => a.best - b.best)\n .map((ranked) => ranked.group);\n}\n"],"mappings":"sFAWA,SAAS,EAAU,EAAsB,CACvC,OAAO,EACJ,UAAU,KAAK,CAAC,CAChB,QAAQ,kBAAmB,EAAE,CAAC,CAC9B,YAAY,CACjB,CAGA,SAAgB,EAAc,EAAoC,CAChE,IAAM,EAAyB,CAAC,EAC5B,EAAwB,CAAE,UAAW,GAAO,QAAS,CAAC,CAAE,EACtD,MAAc,EACd,EAAQ,UAAY,IAAA,IAAa,EAAQ,QAAQ,OAAS,IAAG,EAAO,KAAK,CAAO,CACtF,EACA,IAAK,IAAM,KAAS,EAAO,CACzB,GAAI,EAAa,CAAK,EAAG,CACvB,EAAQ,QAAQ,KAAK,CAAK,EAC1B,QACF,CACA,EAAM,EACN,EAAU,EAAc,CAAK,EACzB,CAAE,QAAS,EAAM,QAAS,UAAW,EAAQ,WAAa,EAAQ,QAAQ,SAAW,EAAG,QAAS,CAAC,CAAE,EACpG,CAAE,UAAW,GAAM,QAAS,CAAC,CAAE,CACrC,CAEA,OADA,EAAM,EACC,EAAO,OAAQ,GAAU,EAAM,QAAQ,OAAS,CAAC,CAC1D,CAQA,SAAS,EAAK,EAAoB,EAAiB,EAA8B,CAC/E,IAAM,EAAQ,OAAO,EAAO,OAAU,SAAW,EAAU,EAAO,KAAK,EAAI,GACrE,GAAY,EAAO,UAAY,CAAC,EAAA,CAAG,IAAI,CAAS,EAChD,EAAW,CAAC,EAAO,GAAG,CAAQ,CAAC,CAAC,KAAK,GAAG,EAC9C,GAAI,CAAC,EAAM,MAAO,GAAS,EAAS,SAAS,CAAI,CAAC,EAAG,OAAO,KAC5D,GAAI,EAAM,WAAW,CAAK,EAAG,MAAO,GACpC,IAAM,EAAuB,GAAiB,EAAK,MAAM,KAAK,CAAC,CAAC,KAAM,GAAS,EAAK,WAAW,EAAM,EAAE,CAAC,EAExG,OADI,EAAoB,CAAK,GAAK,EAAS,KAAK,CAAmB,EAAU,EACtE,CACT,CAWA,SAAgB,EAAe,EAAwB,EAA+B,CACpF,IAAM,EAAa,EAAU,EAAM,KAAK,CAAC,EACzC,GAAI,CAAC,EAAY,OAAO,EACxB,IAAM,EAAQ,EAAW,MAAM,KAAK,EAGpC,OAAO,EACJ,IAAK,GAA8B,CAClC,IAAM,EAAU,EAAM,QACnB,IAAK,IAAY,CAAE,SAAQ,KAAM,EAAK,EAAQ,EAAO,CAAU,CAAE,EAAE,CAAC,CACpE,OAAQ,GAAyD,EAAM,OAAS,IAAI,CAAC,CACrF,MAAM,EAAG,IAAM,EAAE,KAAO,EAAE,IAAI,EAEjC,OADI,EAAQ,SAAW,EAAU,KAC1B,CAEL,MAAO,CAAE,GAAG,EAAO,UAAW,GAAO,QAAS,EAAQ,IAAK,GAAU,EAAM,MAAM,CAAE,EACnF,KAAM,EAAQ,EAAE,CAAC,IACnB,CACF,CAAC,CAAC,CACD,OAAQ,GAAkC,IAAW,IAAI,CAAC,CAC1D,MAAM,EAAG,IAAM,EAAE,KAAO,EAAE,IAAI,CAAC,CAC/B,IAAK,GAAW,EAAO,KAAK,CACjC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{isIconDefinition as n,renderIcon as r}from"../utils/renderIcon.mjs";import i from"../actionIcon/actionIcon.mjs";import a from"../animatedIcon/animatedIcon.mjs";import o from"../hooks/useClipboard.mjs";import s from"./copyButton.module.mjs";import c from"classnames";import{faCheck as l,faCopy as u}from"@fortawesome/free-solid-svg-icons";import{Fragment as d,jsx as f,jsxs as p}from"react/jsx-runtime";var m={copy:`Copy`,copied:`Copied`,failed:`Could not copy`};function h(h){let{value:g,timeout:_=2e3,icon:v=u,copiedIcon:y=l,onCopy:b,onError:x,onClick:S,labels:C,className:w,style:T,classNames:E,styles:D,...O}=e(`CopyButton`,h),k=t(`CopyButton`,C,m),{copy:A,copied:j,error:M}=o({timeout:_}),N=j?k.copied:k.copy,P=j?y:v,F=n(v)&&n(y)?f(a,{icon:j?y:v,classNames:{icon:E?.icon},styles:{icon:D?.icon}}):r(P,{className:E?.icon,style:D?.icon});return p(d,{children:[f(i,{...O,icon:f(d,{children:F}),title:N,"aria-label":N,className:c(s.copyButton,j&&s.copyButtonCopied,w),style:T,classNames:{root:E?.root},styles:{root:D?.root},onClick:async e=>{S?.(e),await A(g)?b?.(g):x?.()}}),f(`span`,{className:s.copyButtonStatus,role:`status`,"aria-live":`polite`,children:j?k.copied:M?k.failed:``})]})}export{h as default};
|
|
2
|
+
//# sourceMappingURL=copyButton.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyButton.mjs","names":[],"sources":["../../../../package/common/copyButton/copyButton.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { faCheck, faCopy } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport AnimatedIcon from '../animatedIcon';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport { useClipboard } from '../hooks/useClipboard';\nimport { isIconDefinition, renderIcon } from '../utils/renderIcon';\nimport type { CopyButtonLabels, CopyButtonProps } from './copyButton.types';\nimport styles from './copyButton.module.pcss';\n\nconst DEFAULT_LABELS: Required<CopyButtonLabels> = {\n copy: 'Copy',\n copied: 'Copied',\n failed: 'Could not copy',\n};\n\nfunction CopyButton(props: CopyButtonProps): ReactElement {\n const {\n value,\n timeout = 2000,\n icon = faCopy,\n copiedIcon = faCheck,\n onCopy,\n onError,\n onClick,\n labels,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('CopyButton', props);\n const text = useLabels('CopyButton', labels, DEFAULT_LABELS);\n const { copy, copied, error } = useClipboard({ timeout });\n\n const label = copied ? text.copied : text.copy;\n const current = copied ? copiedIcon : icon;\n const iconElement =\n isIconDefinition(icon) && isIconDefinition(copiedIcon) ? (\n <AnimatedIcon\n icon={copied ? copiedIcon : icon}\n classNames={{ icon: classNames?.icon }}\n styles={{ icon: slotStyles?.icon }}\n />\n ) : (\n renderIcon(current, { className: classNames?.icon, style: slotStyles?.icon })\n );\n\n return (\n <>\n <ActionIcon\n {...rest}\n icon={<>{iconElement}</>}\n title={label}\n aria-label={label}\n className={cx(styles.copyButton, copied && styles.copyButtonCopied, className)}\n style={style}\n classNames={{ root: classNames?.root }}\n styles={{ root: slotStyles?.root }}\n onClick={async (event) => {\n onClick?.(event);\n if (await copy(value)) onCopy?.(value);\n else onError?.();\n }}\n />\n {/* Beside the button, not in it: a live region inside role=\"button\" is not reliably announced. */}\n <span className={styles.copyButtonStatus} role='status' aria-live='polite'>\n {copied ? text.copied : error ? text.failed : ''}\n </span>\n </>\n );\n}\n\nexport default CopyButton;\n"],"mappings":"ojBAYA,IAAM,EAA6C,CACjD,KAAM,OACN,OAAQ,SACR,OAAQ,gBACV,EAEA,SAAS,EAAW,EAAsC,CACxD,GAAM,CACJ,QACA,UAAU,IACV,OAAO,EACP,aAAa,EACb,SACA,UACA,UACA,SACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,aAAc,CAAK,EACtC,EAAO,EAAU,aAAc,EAAQ,CAAc,EACrD,CAAE,OAAM,SAAQ,SAAU,EAAa,CAAE,SAAQ,CAAC,EAElD,EAAQ,EAAS,EAAK,OAAS,EAAK,KACpC,EAAU,EAAS,EAAa,EAChC,EACJ,EAAiB,CAAI,GAAK,EAAiB,CAAU,EACnD,EAAC,EAAD,CACE,KAAM,EAAS,EAAa,EAC5B,WAAY,CAAE,KAAM,GAAY,IAAK,EACrC,OAAQ,CAAE,KAAM,GAAY,IAAK,CAClC,CAAA,EAED,EAAW,EAAS,CAAE,UAAW,GAAY,KAAM,MAAO,GAAY,IAAK,CAAC,EAGhF,OACE,EAAA,EAAA,CAAA,SAAA,CACE,EAAC,EAAD,CACE,GAAI,EACJ,KAAM,EAAA,EAAA,CAAA,SAAG,CAAc,CAAA,EACvB,MAAO,EACP,aAAY,EACZ,UAAW,EAAG,EAAO,WAAY,GAAU,EAAO,iBAAkB,CAAS,EACtE,QACP,WAAY,CAAE,KAAM,GAAY,IAAK,EACrC,OAAQ,CAAE,KAAM,GAAY,IAAK,EACjC,QAAS,KAAO,IAAU,CACxB,IAAU,CAAK,EACX,MAAM,EAAK,CAAK,EAAG,IAAS,CAAK,EAChC,IAAU,CACjB,CACD,CAAA,EAED,EAAC,OAAD,CAAM,UAAW,EAAO,iBAAkB,KAAK,SAAS,YAAU,SAC/D,SAAA,EAAS,EAAK,OAAS,EAAQ,EAAK,OAAS,EAC1C,CAAA,CACN,CAAA,CAAA,CAEN"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";var e=`copyButton_HEd1K`,t=`copyButton-copied_HL1zN`,n=`copyButton-status_QdwYf`,r={copyButton:e,"copyButton-copied":`copyButton-copied_HL1zN`,copyButtonCopied:t,"copyButton-status":`copyButton-status_QdwYf`,copyButtonStatus:n};export{e as copyButton,t as copyButtonCopied,n as copyButtonStatus,r as default};
|
|
2
|
+
//# sourceMappingURL=copyButton.module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyButton.module.mjs","names":[],"sources":["../../../../package/common/copyButton/copyButton.module.pcss"],"sourcesContent":[".copyButton {\n /* As a block, AnimatedIcon's inline-block box sits on a text baseline and rides high. */\n display: inline-flex;\n\n &-copied {\n color: var(--success-color);\n }\n\n &-status {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n border: 0;\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import e from"../../../interactableDiv/index.mjs";import t from"./datePickerMonth.module.mjs";import{getLocale as n}from"../../../../services/localization.mjs";import{
|
|
1
|
+
"use client";import e from"../../../interactableDiv/index.mjs";import t from"./datePickerMonth.module.mjs";import{getLocale as n}from"../../../../services/localization.mjs";import{dateToDay as r,daysInMonth as i,formatDay as a,parseDay as o}from"../../../utils/day.mjs";import{addDays as s,getStartWeekDayOfMonth as c,getToday as l,getWeekDays as u}from"../../dateFunctions.mjs";import{useEffect as d,useRef as f,useState as p}from"react";import m from"classnames";import{jsx as h,jsxs as g}from"react/jsx-runtime";function _(e,t,n){let r=o(n);if(r&&r.month===e&&r.year===t)return r.day;let i=l();return i.month===e&&i.year===t?i.day:1}function v(e,t,n){return{isStartDate:e===t,isEndDate:e===n,isInRange:!!t&&!!n&&e>=t&&e<=n}}function y(e,t,n){return!!t&&e<t||!!n&&e>n}function b({style:o,className:b=``,month:x=l().month,year:S=l().year,onSelect:C=()=>null,selectionStart:w,selectionEnd:T,minDate:E=null,maxDate:D=null,onNavigateMonth:O}){let k=n(`-`),A=i({year:S,month:x}),j=c(x,S),M=r(new Date),N=f({}),[P,F]=p(()=>_(x,S,w)),I=f(null);d(()=>{if(I.current!=null){let e=I.current;I.current=null,F(e),N.current[e]?.focus()}else F(_(x,S,w))},[x,S]);function L(e,t){let n=0;if(e.key===`ArrowRight`)n=1;else if(e.key===`ArrowLeft`)n=-1;else if(e.key===`ArrowDown`)n=7;else if(e.key===`ArrowUp`)n=-7;else return;e.preventDefault();let r=s(t,x,S,n);r.month!==x||r.year!==S?(I.current=r.day,O?.(r.month>x||r.year>S?1:-1)):(F(r.day),N.current[r.day]?.focus())}return h(`div`,{className:m(t.datePickerMonth,b),style:o,children:g(`div`,{className:m(t.datePickerMonthContent),children:[u(k).map((e,t)=>h(`div`,{children:e},t)),Array.from(Array(j-1).keys()).map(e=>h(`div`,{className:m(t.datePickerMonthItem,t.datePickerMonthPlaceholder)},e)),Array.from(Array(A).keys()).map(n=>{let r=n+1,i=a({day:r,month:x,year:S}),o=v(i,w,T),s=y(i,E,D),c=i===M;return h(e,{ref:e=>{N.current[r]=e},tabIndex:r===P?0:-1,onKeyDown:e=>L(e,r),onClick:()=>s?null:C(i),className:m(t.datePickerMonthDay,t.datePickerMonthItem,{[t.datePickerMonthDaySelected]:o.isInRange,[t.datePickerMonthDaySelectedStart]:o.isStartDate,[t.datePickerMonthDaySelectedEnd]:o.isEndDate,[t.datePickerMonthDayDisabled]:s,[t.datePickerMonthDayToday]:c}),children:r},r)}),Array.from(Array(42-(j+A-1)).keys()).map(e=>h(`div`,{className:m(t.datePickerMonthItem,t.datePickerMonthPlaceholder),children:`\xA0`},e))]})})}export{b as default};
|
|
2
2
|
//# sourceMappingURL=datePickerMonth.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datePickerMonth.mjs","names":[],"sources":["../../../../../../package/common/datePicker/components/datePickerMonth/datePickerMonth.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport styles from './datePickerMonth.module.pcss';\nimport { getLocale } from 'services/localization';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport {\n addDays,\n getDateFromDayMonthAndYear,\n getDayMonthAndYearOfDate,\n getDaysInMonth,\n getStartWeekDayOfMonth,\n getWeekDays,\n} from '../../dateFunctions';\nimport type { DatePickerMonthProps } from './datePickerMonth.types';\n\n// Which day gets the sole tab stop when this month first renders (or when the displayed\n// month changes via the header, not via arrow navigation): the selected day if it falls in\n// this month, else today if it falls in this month, else the 1st.\nfunction getDefaultFocusedDay(month: number, year: number, selectionStart: Date | undefined): number {\n if (selectionStart) {\n const sel = getDayMonthAndYearOfDate(selectionStart);\n if (sel.month === month && sel.year === year) return sel.day;\n }\n const today = getDayMonthAndYearOfDate(new Date());\n if (today.month === month && today.year === year) return today.day;\n return 1;\n}\n\nfunction checkSelected(\n day: number,\n month: number,\n year: number,\n selectionStart: Date | undefined,\n selectionEnd: Date | undefined,\n) {\n const {\n day: startDay,\n month: startMonth,\n year: startYear,\n } = selectionStart ? getDayMonthAndYearOfDate(selectionStart) : { day: undefined, month: undefined, year: undefined };\n const {\n day: endDay,\n month: endMonth,\n year: endYear,\n } = selectionEnd ? getDayMonthAndYearOfDate(selectionEnd) : { day: undefined, month: undefined, year: undefined };\n\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n const isStartDate = day === startDay && month === startMonth && year === startYear;\n const isEndDate = day === endDay && month === endMonth && year === endYear;\n\n let isInRange = false;\n if (\n startDay !== undefined &&\n startMonth !== undefined &&\n startYear !== undefined &&\n endDay !== undefined &&\n endMonth !== undefined &&\n endYear !== undefined\n ) {\n const selectionStartNoTime = getDateFromDayMonthAndYear(startDay, startMonth, startYear);\n const selectionEndNoTime = getDateFromDayMonthAndYear(endDay, endMonth, endYear);\n isInRange =\n toCheckNoTime.getTime() >= selectionStartNoTime.getTime() &&\n toCheckNoTime.getTime() <= selectionEndNoTime.getTime();\n }\n\n return { isStartDate, isInRange, isEndDate };\n}\n\nfunction checkDisabled(\n day: number,\n month: number,\n year: number,\n minDate: Date | null | undefined,\n maxDate: Date | null | undefined,\n): boolean {\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n if (minDate) {\n const { day: minDay, month: minMonth, year: minYear } = getDayMonthAndYearOfDate(minDate);\n if (toCheckNoTime < getDateFromDayMonthAndYear(minDay, minMonth, minYear)) return true;\n }\n\n if (maxDate) {\n const { day: maxDay, month: maxMonth, year: maxYear } = getDayMonthAndYearOfDate(maxDate);\n if (toCheckNoTime > getDateFromDayMonthAndYear(maxDay, maxMonth, maxYear)) return true;\n }\n\n return false;\n}\n\nfunction checkIsToday(day: number, month: number, year: number): boolean {\n const { day: currDay, month: currMonth, year: currYear } = getDayMonthAndYearOfDate(new Date());\n return day === currDay && month === currMonth && year === currYear;\n}\n\nexport default function DatePickerMonth({\n style,\n className = '',\n month = new Date().getMonth() + 1,\n year = new Date().getFullYear(),\n onSelect = () => null,\n selectionStart,\n selectionEnd,\n minDate = null,\n maxDate = null,\n onNavigateMonth,\n}: DatePickerMonthProps) {\n const locale = getLocale('-');\n const daysInMonth = getDaysInMonth(month, year);\n const startWeekDayOfMonth = getStartWeekDayOfMonth(month, year);\n\n const dayRefs = useRef<Record<number, HTMLDivElement | null>>({});\n const [focusedDay, setFocusedDay] = useState(() => getDefaultFocusedDay(month, year, selectionStart));\n\n // A day arrowed onto in an adjacent month, waiting for that month's grid to render so it\n // can be focused. `onNavigateMonth` only shifts `month`/`year` — the actual DOM focus has\n // to happen after this component re-renders with the new days, hence the effect below.\n const pendingFocusDayRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (pendingFocusDayRef.current != null) {\n const day = pendingFocusDayRef.current;\n pendingFocusDayRef.current = null;\n setFocusedDay(day);\n dayRefs.current[day]?.focus();\n } else {\n // The displayed month changed some other way (header chevrons, month/year dropdowns) —\n // re-pick a sensible tab stop, but don't steal focus from whatever the user just used.\n setFocusedDay(getDefaultFocusedDay(month, year, selectionStart));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [month, year]);\n\n function handleDayKeyDown(event: React.KeyboardEvent<HTMLDivElement>, day: number) {\n let delta = 0;\n if (event.key === 'ArrowRight') delta = 1;\n else if (event.key === 'ArrowLeft') delta = -1;\n else if (event.key === 'ArrowDown') delta = 7;\n else if (event.key === 'ArrowUp') delta = -7;\n else return;\n\n event.preventDefault();\n const next = addDays(day, month, year, delta);\n\n if (next.month !== month || next.year !== year) {\n pendingFocusDayRef.current = next.day;\n onNavigateMonth?.(next.month > month || next.year > year ? 1 : -1);\n } else {\n setFocusedDay(next.day);\n dayRefs.current[next.day]?.focus();\n }\n }\n\n return (\n <div className={cx(styles.datePickerMonth, className)} style={style}>\n <div className={cx(styles.datePickerMonthContent)}>\n {getWeekDays(locale).map((weekDay, index) => (\n <div key={index}>{weekDay}</div>\n ))}\n {Array.from(Array(startWeekDayOfMonth - 1).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)} />\n ))}\n {Array.from(Array(daysInMonth).keys()).map((index) => {\n const day = index + 1;\n const selectedRes = checkSelected(day, month, year, selectionStart, selectionEnd);\n const isDisabled = checkDisabled(day, month, year, minDate, maxDate);\n const isToday = checkIsToday(day, month, year);\n\n return (\n <InteractableDiv\n key={day}\n ref={(el) => {\n dayRefs.current[day] = el;\n }}\n tabIndex={day === focusedDay ? 0 : -1}\n onKeyDown={(event) => handleDayKeyDown(event, day)}\n onClick={() => (isDisabled ? null : onSelect(getDateFromDayMonthAndYear(day, month, year)))}\n className={cx(styles.datePickerMonthDay, styles.datePickerMonthItem, {\n [styles.datePickerMonthDaySelected]: selectedRes.isInRange,\n [styles.datePickerMonthDaySelectedStart]: selectedRes.isStartDate,\n [styles.datePickerMonthDaySelectedEnd]: selectedRes.isEndDate,\n [styles.datePickerMonthDayDisabled]: isDisabled,\n [styles.datePickerMonthDayToday]: isToday,\n })}\n >\n {day}\n </InteractableDiv>\n );\n })}\n {Array.from(Array(42 - (startWeekDayOfMonth + daysInMonth - 1)).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}>\n \n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"datePickerMonth.mjs","names":[],"sources":["../../../../../../package/common/datePicker/components/datePickerMonth/datePickerMonth.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport styles from './datePickerMonth.module.pcss';\nimport { getLocale } from 'services/localization';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport { dateToDay, daysInMonth, formatDay, parseDay } from 'components/common/utils/day';\nimport { addDays, getStartWeekDayOfMonth, getToday, getWeekDays } from '../../dateFunctions';\nimport type { DatePickerMonthProps } from './datePickerMonth.types';\n\n// Which day gets the sole tab stop when this month first renders (or when the displayed\n// month changes via the header, not via arrow navigation): the selected day if it falls in\n// this month, else today if it falls in this month, else the 1st.\nfunction getDefaultFocusedDay(month: number, year: number, selectionStart: string | null | undefined): number {\n const selected = parseDay(selectionStart);\n if (selected && selected.month === month && selected.year === year) return selected.day;\n const today = getToday();\n if (today.month === month && today.year === year) return today.day;\n return 1;\n}\n\n// `'YYYY-MM-DD'` sorts as it reads, so days compare as plain strings.\nfunction checkSelected(value: string, start: string | null | undefined, end: string | null | undefined) {\n return {\n isStartDate: value === start,\n isEndDate: value === end,\n isInRange: !!start && !!end && value >= start && value <= end,\n };\n}\n\nfunction checkDisabled(value: string, minDate: string | null | undefined, maxDate: string | null | undefined): boolean {\n return (!!minDate && value < minDate) || (!!maxDate && value > maxDate);\n}\n\nexport default function DatePickerMonth({\n style,\n className = '',\n month = getToday().month,\n year = getToday().year,\n onSelect = () => null,\n selectionStart,\n selectionEnd,\n minDate = null,\n maxDate = null,\n onNavigateMonth,\n}: DatePickerMonthProps) {\n const locale = getLocale('-');\n const dayCount = daysInMonth({ year, month });\n const startWeekDayOfMonth = getStartWeekDayOfMonth(month, year);\n const today = dateToDay(new Date());\n\n const dayRefs = useRef<Record<number, HTMLDivElement | null>>({});\n const [focusedDay, setFocusedDay] = useState(() => getDefaultFocusedDay(month, year, selectionStart));\n\n // A day arrowed onto in an adjacent month, waiting for that month's grid to render so it\n // can be focused. `onNavigateMonth` only shifts `month`/`year` — the actual DOM focus has\n // to happen after this component re-renders with the new days, hence the effect below.\n const pendingFocusDayRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (pendingFocusDayRef.current != null) {\n const day = pendingFocusDayRef.current;\n pendingFocusDayRef.current = null;\n setFocusedDay(day);\n dayRefs.current[day]?.focus();\n } else {\n // The displayed month changed some other way (header chevrons, month/year dropdowns) —\n // re-pick a sensible tab stop, but don't steal focus from whatever the user just used.\n setFocusedDay(getDefaultFocusedDay(month, year, selectionStart));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [month, year]);\n\n function handleDayKeyDown(event: React.KeyboardEvent<HTMLDivElement>, day: number) {\n let delta = 0;\n if (event.key === 'ArrowRight') delta = 1;\n else if (event.key === 'ArrowLeft') delta = -1;\n else if (event.key === 'ArrowDown') delta = 7;\n else if (event.key === 'ArrowUp') delta = -7;\n else return;\n\n event.preventDefault();\n const next = addDays(day, month, year, delta);\n\n if (next.month !== month || next.year !== year) {\n pendingFocusDayRef.current = next.day;\n onNavigateMonth?.(next.month > month || next.year > year ? 1 : -1);\n } else {\n setFocusedDay(next.day);\n dayRefs.current[next.day]?.focus();\n }\n }\n\n return (\n <div className={cx(styles.datePickerMonth, className)} style={style}>\n <div className={cx(styles.datePickerMonthContent)}>\n {getWeekDays(locale).map((weekDay, index) => (\n <div key={index}>{weekDay}</div>\n ))}\n {Array.from(Array(startWeekDayOfMonth - 1).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)} />\n ))}\n {Array.from(Array(dayCount).keys()).map((index) => {\n const day = index + 1;\n const value = formatDay({ day, month, year });\n const selectedRes = checkSelected(value, selectionStart, selectionEnd);\n const isDisabled = checkDisabled(value, minDate, maxDate);\n const isToday = value === today;\n\n return (\n <InteractableDiv\n key={day}\n ref={(el) => {\n dayRefs.current[day] = el;\n }}\n tabIndex={day === focusedDay ? 0 : -1}\n onKeyDown={(event) => handleDayKeyDown(event, day)}\n onClick={() => (isDisabled ? null : onSelect(value))}\n className={cx(styles.datePickerMonthDay, styles.datePickerMonthItem, {\n [styles.datePickerMonthDaySelected]: selectedRes.isInRange,\n [styles.datePickerMonthDaySelectedStart]: selectedRes.isStartDate,\n [styles.datePickerMonthDaySelectedEnd]: selectedRes.isEndDate,\n [styles.datePickerMonthDayDisabled]: isDisabled,\n [styles.datePickerMonthDayToday]: isToday,\n })}\n >\n {day}\n </InteractableDiv>\n );\n })}\n {Array.from(Array(42 - (startWeekDayOfMonth + dayCount - 1)).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}>\n \n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{getLocale as e}from"../../services/localization.mjs";
|
|
1
|
+
"use client";import{getLocale as e}from"../../services/localization.mjs";import{dateToDay as t,daysInMonth as n,formatDay as r,parseDay as i}from"../utils/day.mjs";function a(e,t,n){let r=new Date(0);return r.setUTCFullYear(e,t-1,n),r}function o(e,t,n,r,i=!1){return a(t,n,r).toLocaleDateString(e,{month:i?`short`:`long`,timeZone:`UTC`})}function s(t=e(`-`)){return Array.from(Array(12).keys()).map(e=>o(t,2023,e+1,1))}function c(e,t=!0){return Array.from(Array(7).keys()).map(n=>a(2023,4,10+n).toLocaleDateString(e,{weekday:t?`short`:`long`,timeZone:`UTC`}))}function l(e,t){return a(t,e,1).getUTCDay()||7}function u(e,t,r,i){let a=e+i,o=t,s=r;for(;a<1;)--o,o<1&&(o=12,--s),a+=n({year:s,month:o});for(;a>n({year:s,month:o});)a-=n({year:s,month:o}),o+=1,o>12&&(o=1,s+=1);return{day:a,month:o,year:s}}function d(){return i(t(new Date))}function f(e){let t=i(e);return t?`${String(t.day).padStart(2,`0`)}.${String(t.month).padStart(2,`0`)}.${String(t.year).padStart(4,`0`)}`:``}function p(e){let t=/^(\d{2})\.(\d{2})\.(\d{4})$/.exec(e);if(!t)return null;let n=r({day:Number(t[1]),month:Number(t[2]),year:Number(t[3])});return i(n)?n:null}function m(e,t,n){let r=e,i=n;return r[0]!==`_`&&(r[0]>`3`?(r=`0${r[0]}${t.substring(2)}`,i={start:3,end:3}):r[0]===`3`&&r[1]!==`_`&&r[1]>`1`&&(r=`0${r[1]}${t.substring(2)}`,i={start:3,end:3})),r[3]!==`_`&&r[3]>`1`&&(r=`${r.substring(0,3)}0${r[3]}${t.substring(5)}`,i={start:6,end:6}),r[3]===`1`&&r[4]!==`_`&&r[4]>`2`&&(r=`${r.substring(0,3)}${r[3]}2${t.substring(5)}`),{value:r,selection:i}}export{u as addDays,m as correctDateMaskValue,f as getDateString,o as getMonthName,s as getMonthNames,l as getStartWeekDayOfMonth,d as getToday,c as getWeekDays,p as parseDateString};
|
|
2
2
|
//# sourceMappingURL=dateFunctions.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dateFunctions.mjs","names":[],"sources":["../../../../package/common/datePicker/dateFunctions.ts"],"sourcesContent":["import { getLocale } from 'services/localization';\n\
|
|
1
|
+
{"version":3,"file":"dateFunctions.mjs","names":[],"sources":["../../../../package/common/datePicker/dateFunctions.ts"],"sourcesContent":["import { getLocale } from 'services/localization';\nimport { dateToDay, daysInMonth, formatDay, parseDay, type DayParts } from '../utils/day';\n\n// Labels are formatted from a UTC date in UTC, so no time zone can move them onto another day.\n// `setUTCFullYear` rather than `Date.UTC`, which reads the years 0 to 99 as 1900 to 1999.\nfunction utcDate(year: number, month: number, day: number): Date {\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, day);\n return date;\n}\n\nexport function getMonthName(locale: string, year: number, month: number, day: number, short = false): string {\n return utcDate(year, month, day).toLocaleDateString(locale, { month: short ? 'short' : 'long', timeZone: 'UTC' });\n}\n\nexport function getMonthNames(locale = getLocale('-')): string[] {\n return Array.from(Array(12).keys()).map((index) => getMonthName(locale, 2023, index + 1, 1));\n}\n\nexport function getWeekDays(locale: string, short = true): string[] {\n // 10 April 2023 was a Monday.\n return Array.from(Array(7).keys()).map((index) =>\n utcDate(2023, 4, 10 + index).toLocaleDateString(locale, { weekday: short ? 'short' : 'long', timeZone: 'UTC' }),\n );\n}\n\n/** 1 (Monday) to 7 (Sunday). */\nexport function getStartWeekDayOfMonth(month: number, year: number): number {\n return utcDate(year, month, 1).getUTCDay() || 7;\n}\n\n/** `delta` days from a day, rolling over into the months and years around it. */\nexport function addDays(day: number, month: number, year: number, delta: number): DayParts {\n let d = day + delta;\n let m = month;\n let y = year;\n while (d < 1) {\n m -= 1;\n if (m < 1) {\n m = 12;\n y -= 1;\n }\n d += daysInMonth({ year: y, month: m });\n }\n while (d > daysInMonth({ year: y, month: m })) {\n d -= daysInMonth({ year: y, month: m });\n m += 1;\n if (m > 12) {\n m = 1;\n y += 1;\n }\n }\n return { day: d, month: m, year: y };\n}\n\n/** Today in the user's time zone. */\nexport function getToday(): DayParts {\n return parseDay(dateToDay(new Date()))!;\n}\n\n/** A `'YYYY-MM-DD'` day as the field shows it, `dd.mm.yyyy`, or `''` for anything else. */\nexport function getDateString(value: string | null | undefined): string {\n const parts = parseDay(value);\n if (!parts) return '';\n return `${String(parts.day).padStart(2, '0')}.${String(parts.month).padStart(2, '0')}.${String(parts.year).padStart(4, '0')}`;\n}\n\n/** What the field holds, `dd.mm.yyyy`, as `'YYYY-MM-DD'`; `null` while incomplete, or for a day that does not exist. */\nexport function parseDateString(text: string): string | null {\n const match = /^(\\d{2})\\.(\\d{2})\\.(\\d{4})$/.exec(text);\n if (!match) return null;\n const value = formatDay({ day: Number(match[1]), month: Number(match[2]), year: Number(match[3]) });\n return parseDay(value) ? value : null;\n}\n\nexport interface DateMaskSelection {\n start: number;\n end: number;\n}\n\nexport interface DateMaskState {\n value: string;\n selection: DateMaskSelection | null;\n}\n\n/**\n * Auto-corrects a partially typed `dd.mm.yyyy` mask value so a single out-of-range\n * digit doesn't force the user to backtrack:\n * - a day \"tens\" digit > 3 (e.g. typing `4`) becomes `04` and the caret jumps to the month\n * - a day of `3x` where x > 1 (e.g. `35`) becomes `0x`\n * - a month \"tens\" digit > 1 (e.g. `2`) becomes `02` and the caret jumps to the year\n * - a month `1x` where x > 2 (e.g. `13`) is clamped to `12`\n *\n * `previousValue` supplies the digits to retain for the part of the field that isn't\n * being rewritten. The returned `selection` is the adjusted caret position, or the\n * passed-in `selection` when no correction applies.\n */\nexport function correctDateMaskValue(\n nextValue: string,\n previousValue: string,\n selection: DateMaskSelection | null,\n): DateMaskState {\n let value = nextValue;\n let nextSelection = selection;\n\n if (value[0] !== '_') {\n if (value[0] > '3') {\n value = `0${value[0]}${previousValue.substring(2)}`;\n nextSelection = { start: 3, end: 3 };\n } else if (value[0] === '3') {\n if (value[1] !== '_' && value[1] > '1') {\n value = `0${value[1]}${previousValue.substring(2)}`;\n nextSelection = { start: 3, end: 3 };\n }\n }\n }\n if (value[3] !== '_' && value[3] > '1') {\n value = `${value.substring(0, 3)}0${value[3]}${previousValue.substring(5)}`;\n nextSelection = { start: 6, end: 6 };\n }\n if (value[3] === '1' && value[4] !== '_' && value[4] > '2') {\n value = `${value.substring(0, 3)}${value[3]}2${previousValue.substring(5)}`;\n }\n\n return { value, selection: nextSelection };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../button/button.mjs";import n from"../actionIcon/actionIcon.mjs";import{PopoverAlign as r,PopoverPlacement as
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../button/button.mjs";import n from"../actionIcon/actionIcon.mjs";import{PopoverAlign as r,PopoverPlacement as ee}from"../popover/popover.types.mjs";import te from"../popover/popover.mjs";import ne from"../tooltip/tooltip.mjs";import re from"../input/input.mjs";import ie from"../modal/modal.mjs";import{getLocale as ae}from"../../services/localization.mjs";import{asDay as i,parseDay as a}from"../utils/day.mjs";import{correctDateMaskValue as oe,getDateString as o,getMonthName as se,getMonthNames as ce,getToday as s,parseDateString as le}from"./dateFunctions.mjs";import ue from"./components/datePickerMonth/datePickerMonth.mjs";import c from"../dropdown/dropdown.mjs";import de from"../maskedInput/maskedInput.mjs";import l from"./datePicker.module.mjs";import{useEffect as u,useRef as d,useState as f}from"react";import p from"classnames";import{faChevronLeft as fe,faChevronRight as pe}from"@fortawesome/free-solid-svg-icons";import{Fragment as me,jsx as m,jsxs as h}from"react/jsx-runtime";function he(e){return e==null||e===``||i(e)?null:Object.prototype.toString.call(e)===`[object Date]`?`a Date. Convert it with dateToDay()`:`${JSON.stringify(e)}, which is not a day`}function g(g){let{className:ge=``,selected:_,onSelect:_e=()=>null,formValidator:v=null,noInput:ve=!1,noHeader:ye=!1,isModal:y=!1,isInline:b=!1,onChange:be=()=>null,minDate:x=null,maxDate:S=null,children:xe=null,showClearButton:Se=!1,label:C=``,isValid:Ce=!0,errorMessage:w=``,isRequired:we=!1,startDate:T,endDate:E,style:Te,classNames:D,styles:O,...Ee}=e(`DatePicker`,g),k=()=>i(v?v.value:_),A=i(x),j=i(S),M=k(),N=a(M)??s(),[P,F]=f(N.month),[I,L]=f(N.year),[R,z]=f(!1),[B,V]=f(()=>o(M)),[De,H]=f(!1),[Oe,U]=f(!1),[,ke]=f(0),[Ae,je]=f(_),W=d(v);if(Ae!==_){je(_);let e=a(_)??s();F(e.month),L(e.year),V(o(_))}let G=d(new Set),K=v?.value;u(()=>{let e={selected:_,formValidator:K,minDate:x,maxDate:S,startDate:T,endDate:E};for(let[t,n]of Object.entries(e)){let e=he(n);e&&!G.current.has(t)&&(G.current.add(t),console.warn(`DatePicker: \`${t}\` takes a day as a 'YYYY-MM-DD' string, and got ${e}. See "Migration from Date values" in docs/DatePicker.md.`))}},[_,K,x,S,T,E]),u(()=>{if(W.current=v,!v)return;v.label=C,v.validate();let e=()=>{let e=a(v.value);e&&(F(e.month),L(e.year)),V(o(v.value)),ke(e=>e+1)};return v.registerOnUpdateListener(e),()=>v.removeOnUpdateListener(e)},[v,C]);let Me=()=>v?v.touched&&v.hasError():!Ce||!!w,Ne=()=>!!(we||v?.validators.find(e=>e.validatorId===`required`)),q=e=>{V(o(e)),v&&v.set(e),be(e)},J=e=>{q(e),_e(e),z(!1)},Y=e=>{let t=I*12+P-1+e,n=Math.floor(t/12);n<0||n>9999||(L(n),F(t%12+1))},X=e=>{let t=le(e);return!t||A&&t<A||j&&t>j?null:t},Pe=({previousState:e,nextState:t})=>{if(t.value===e.value)return t;let n=oe(t.value,e.value,t.selection??null),r=X(n.value);return r&&q(r),n},Fe=()=>{let e=400,t=s().year-200,n=a(A),r=a(j);return n&&(t=n.year),r&&(e=Math.max(0,r.year-t+1)),Array.from(Array(e).keys()).map(e=>({key:e+t,label:e+t}))},Z=k(),Ie=Me(),Le=ye?null:h(`div`,{className:p(l.datePickerHeader,D?.header),style:O?.header,children:[m(n,{icon:fe,onClick:()=>Y(-1)}),m(`div`,{className:l.datePickerHeaderMonthAndYearContainer,children:h(`div`,{className:l.datePickerHeaderMonthAndYear,children:[m(c,{plainStyle:!0,scrollToSelected:!0,onChange:e=>F(e),className:p(l.datePickerHeaderMonth,D?.monthDropdown),style:O?.monthDropdown,value:se(ae(`-`),I,P,1),items:ce().map((e,t)=>({key:t+1,label:e}))}),m(c,{plainStyle:!0,scrollToSelected:!0,useMatLabelStyle:!1,className:p(l.datePickerHeaderYear,D?.yearDropdown),style:O?.yearDropdown,onChange:e=>L(e),value:I,items:Fe()})]})}),m(n,{icon:pe,onClick:()=>Y(1)})]}),Q=h(me,{children:[Le,m(ue,{className:p(l.datePickerMonth,D?.calendar),style:O?.calendar,month:P,year:I,onSelect:J,selectionStart:i(T)??Z,selectionEnd:i(E)??Z,minDate:A,maxDate:j,onNavigateMonth:Y}),Se&&m(t,{onClick:()=>J(null),className:D?.clearButton,style:O?.clearButton,children:`Clear`}),xe]}),$=ve?null:m(re,{autoComplete:`off`,className:D?.input,style:O?.input,readOnly:y,classNames:y?{input:l.datePickerModalInput}:void 0,label:`${C}${Ne()?` *`:``}`,value:B,onChange:e=>V(e),onClick:()=>z(!0),customInput:m(de,{mask:`99.99.9999`,beforeMaskedStateChange:Pe}),onBlur:()=>{W.current&&(W.current.touched=!0),H(!1),B!==o(k())&&q(X(B))},onFocus:()=>H(!0),onMouseEnter:()=>U(!0),onMouseLeave:()=>U(!1),isValid:!Ie}),Re=b?Q:y?m(ie,{hideHeader:!0,isOpen:R,onClose:()=>z(!1),children:Q}):m(te,{isOpen:R,onOpenChange:e=>z(e),content:Q,placement:ee.Bottom,align:r.Start,closeOnTriggerClick:!1,constrainWidth:!1,children:$});return h(`div`,{...Ee,className:p(l.datePicker,ge,D?.root),style:{...Te,...O?.root},children:[(y||b)&&$,Re,m(ne,{variant:`error`,message:v?v.getCurrentErrorMessage():w||``,isVisible:Ie&&(De||Oe)})]})}export{g as default};
|
|
2
2
|
//# sourceMappingURL=datePicker.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datePicker.mjs","names":[],"sources":["../../../../package/common/datePicker/datePicker.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\nimport { useComponentDefaults } from '../configProvider';\nimport DatePickerMonth from './components/datePickerMonth';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\nimport { getLocale } from 'services/localization';\nimport ActionIcon from '../actionIcon';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Dropdown from '../dropdown';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport {\n getDateFromDayMonthAndYear,\n getMonthName,\n getMonthNames,\n getDateString,\n correctDateMaskValue,\n} from './dateFunctions';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport type { DatePickerProps } from './datePicker.types';\n\nimport styles from './datePicker.module.pcss';\n\nexport default function DatePicker(props: DatePickerProps) {\n const {\n className = '',\n selected,\n onSelect = () => null,\n formValidator = null,\n noInput = false,\n noHeader = false,\n isModal = false,\n isInline = false,\n onChange = () => null,\n minDate = null,\n maxDate = null,\n children = null,\n showClearButton = false,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n startDate,\n endDate,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('DatePicker', props);\n const getCurrValue = (): Date | undefined => (formValidator ? (formValidator.value as Date) : selected);\n\n const initialDate = getCurrValue() ?? new Date();\n\n const [currentMonth, setCurrentMonth] = useState(initialDate.getMonth() + 1);\n const [currentYear, setCurrentYear] = useState(initialDate.getFullYear());\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [currentDateString, setCurrentDateString] = useState(() => (getCurrValue() ? getDateString(initialDate) : ''));\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const [prevSelected, setPrevSelected] = useState(selected);\n\n const fvRef = useRef(formValidator);\n\n // Sync navigation view when `selected` prop changes externally\n if (prevSelected !== selected) {\n setPrevSelected(selected);\n const d = selected ?? new Date();\n setCurrentMonth(d.getMonth() + 1);\n setCurrentYear(d.getFullYear());\n setCurrentDateString(selected ? getDateString(selected) : '');\n }\n\n // Subscribe to formValidator updates (external system → setState in callback)\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n const val = formValidator.value as Date | undefined;\n if (val) {\n setCurrentMonth(val.getMonth() + 1);\n setCurrentYear(val.getFullYear());\n setCurrentDateString(getDateString(val));\n } else {\n setCurrentDateString('');\n }\n forceUpdate((n: number) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean => {\n return formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n };\n\n const computedIsRequired = (): boolean => {\n return !!(\n isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n );\n };\n\n const handleChange = (date: Date | null) => {\n setCurrentDateString(date ? getDateString(date) : '');\n if (formValidator) formValidator.set(date);\n onChange(date);\n };\n\n const handleSelect = (date: Date | null) => {\n handleChange(date);\n onSelect(date);\n setIsPickerOpen(false);\n };\n\n const changeMonth = (delta: number) => {\n setCurrentMonth((prev) => {\n let next = prev + delta;\n if (next < 1) {\n next = 12;\n setCurrentYear((y) => y - 1);\n } else if (next > 12) {\n next = 1;\n setCurrentYear((y) => y + 1);\n }\n return next;\n });\n };\n\n const tryParseDateString = (dateString: string): Date | null => {\n if (dateString.match(/\\d{2}\\.\\d{2}\\.\\d{4}/gi)) {\n const [day, month, year] = dateString.split('.');\n const parsedDate = getDateFromDayMonthAndYear(Number(day), Number(month), Number(year));\n if (parsedDate && parsedDate.toString() !== 'Invalid Date') {\n const isSmallerThanMaxDate = !maxDate || parsedDate <= maxDate;\n const isBiggerThanMinDate = !minDate || parsedDate >= minDate;\n if (isSmallerThanMaxDate && isBiggerThanMinDate) return parsedDate;\n }\n }\n return null;\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n // A change that moved nothing needs no correcting, and re-running the day/month padding on\n // an unchanged value would fight the caret the mask just placed.\n if (nextState.value === previousState.value) return nextState;\n\n const corrected = correctDateMaskValue(nextState.value, previousState.value, nextState.selection ?? null);\n\n const parsedDate = tryParseDateString(corrected.value);\n if (parsedDate) handleChange(parsedDate);\n\n return corrected;\n };\n\n const getYearDropdownOptions = () => {\n let length = 400;\n let zeroOffset = new Date().getFullYear() - 200;\n if (minDate) zeroOffset = minDate.getFullYear();\n if (maxDate) length = maxDate.getFullYear() - zeroOffset + 1;\n return Array.from(Array(length).keys()).map((i) => ({ key: i + zeroOffset, label: i + zeroOffset }));\n };\n\n const currValue = getCurrValue();\n const hasErr = hasError();\n\n const header = noHeader ? null : (\n <div className={cx(styles.datePickerHeader, classNames?.header)} style={slotStyles?.header}>\n <ActionIcon icon={faChevronLeft} onClick={() => changeMonth(-1)} />\n <div className={styles.datePickerHeaderMonthAndYearContainer}>\n <div className={styles.datePickerHeaderMonthAndYear}>\n <Dropdown\n plainStyle\n scrollToSelected\n onChange={(v) => setCurrentMonth(v as number)}\n className={cx(styles.datePickerHeaderMonth, classNames?.monthDropdown)}\n style={slotStyles?.monthDropdown}\n value={getMonthName(getLocale('-'), currentYear, currentMonth, 1)}\n items={getMonthNames().map((month, index) => ({ key: index + 1, label: month }))}\n />\n <Dropdown\n plainStyle\n scrollToSelected\n useMatLabelStyle={false}\n className={cx(styles.datePickerHeaderYear, classNames?.yearDropdown)}\n style={slotStyles?.yearDropdown}\n onChange={(v) => setCurrentYear(v as number)}\n value={currentYear}\n items={getYearDropdownOptions()}\n />\n </div>\n </div>\n <ActionIcon icon={faChevronRight} onClick={() => changeMonth(1)} />\n </div>\n );\n\n const pickerContent = (\n <>\n {header}\n <DatePickerMonth\n className={cx(styles.datePickerMonth, classNames?.calendar)}\n style={slotStyles?.calendar}\n month={currentMonth}\n year={currentYear}\n onSelect={handleSelect}\n selectionStart={startDate ?? currValue}\n selectionEnd={endDate ?? currValue}\n minDate={minDate}\n maxDate={maxDate}\n onNavigateMonth={changeMonth}\n />\n {showClearButton && (\n <Button onClick={() => handleSelect(null)} className={classNames?.clearButton} style={slotStyles?.clearButton}>\n Clear\n </Button>\n )}\n {children}\n </>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n className={classNames?.input}\n style={slotStyles?.input}\n readOnly={isModal}\n classNames={isModal ? { input: styles.datePickerModalInput } : undefined}\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentDateString}\n onChange={(v) => setCurrentDateString(v as string)}\n onClick={() => setIsPickerOpen(true)}\n customInput={<MaskedInput mask='99.99.9999' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onBlur={() => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n handleChange(tryParseDateString(currentDateString));\n }}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n isValid={!hasErr}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={(open: boolean) => setIsPickerOpen(open)}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n {...rest}\n className={cx(styles.datePicker, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"datePicker.mjs","names":[],"sources":["../../../../package/common/datePicker/datePicker.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\nimport { useComponentDefaults } from '../configProvider';\nimport DatePickerMonth from './components/datePickerMonth';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\nimport { getLocale } from 'services/localization';\nimport ActionIcon from '../actionIcon';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Dropdown from '../dropdown';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { asDay, parseDay } from '../utils/day';\nimport {\n getMonthName,\n getMonthNames,\n getDateString,\n getToday,\n parseDateString,\n correctDateMaskValue,\n} from './dateFunctions';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport type { FormValidator } from 'services/formValidation';\nimport type { DatePickerProps } from './datePicker.types';\n\nimport styles from './datePicker.module.pcss';\n\n/**\n * Why `value` is not a day, or `null` when it is one or is empty. Days were `Date`s before 0.39,\n * and stored as their JSON, a timestamp; either still gets through a loosely typed validator or\n * plain JavaScript, and would otherwise just show an empty field.\n */\nfunction notADay(value: unknown): string | null {\n if (value === null || value === undefined || value === '' || asDay(value)) return null;\n if (Object.prototype.toString.call(value) === '[object Date]') return 'a Date. Convert it with dateToDay()';\n return `${JSON.stringify(value)}, which is not a day`;\n}\n\nexport default function DatePicker(props: DatePickerProps) {\n const {\n className = '',\n selected,\n onSelect = () => null,\n formValidator = null,\n noInput = false,\n noHeader = false,\n isModal = false,\n isInline = false,\n onChange = () => null,\n minDate = null,\n maxDate = null,\n children = null,\n showClearButton = false,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n startDate,\n endDate,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('DatePicker', props);\n const getCurrValue = (): string | null => asDay(formValidator ? formValidator.value : selected);\n const minDay = asDay(minDate);\n const maxDay = asDay(maxDate);\n\n const initialValue = getCurrValue();\n const initialDay = parseDay(initialValue) ?? getToday();\n\n const [currentMonth, setCurrentMonth] = useState(initialDay.month);\n const [currentYear, setCurrentYear] = useState(initialDay.year);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [currentDateString, setCurrentDateString] = useState(() => getDateString(initialValue));\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const [prevSelected, setPrevSelected] = useState(selected);\n\n const fvRef = useRef(formValidator);\n\n // Sync navigation view when `selected` prop changes externally\n if (prevSelected !== selected) {\n setPrevSelected(selected);\n const shown = parseDay(selected) ?? getToday();\n setCurrentMonth(shown.month);\n setCurrentYear(shown.year);\n setCurrentDateString(getDateString(selected));\n }\n\n // Once per prop: a `new Date()` written inline is a new object on every render.\n const warned = useRef(new Set<string>());\n const validatorValue: unknown = formValidator?.value;\n useEffect(() => {\n const values = { selected, formValidator: validatorValue, minDate, maxDate, startDate, endDate };\n for (const [name, value] of Object.entries(values)) {\n const problem = notADay(value);\n if (!problem || warned.current.has(name)) continue;\n warned.current.add(name);\n console.warn(\n `DatePicker: \\`${name}\\` takes a day as a 'YYYY-MM-DD' string, and got ${problem}. ` +\n `See \"Migration from Date values\" in docs/DatePicker.md.`,\n );\n }\n }, [selected, validatorValue, minDate, maxDate, startDate, endDate]);\n\n // Subscribe to formValidator updates (external system → setState in callback)\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n formValidator.label = label;\n formValidator.validate();\n const listener = () => {\n const shown = parseDay(formValidator.value);\n if (shown) {\n setCurrentMonth(shown.month);\n setCurrentYear(shown.year);\n }\n setCurrentDateString(getDateString(formValidator.value));\n forceUpdate((n: number) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator, label]);\n\n const hasError = (): boolean => {\n return formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n };\n\n const computedIsRequired = (): boolean => {\n return !!(\n isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n );\n };\n\n const handleChange = (day: string | null) => {\n setCurrentDateString(getDateString(day));\n // Typed as a union so each validator TypeScript infers for a day fits; all of them hold one.\n if (formValidator) (formValidator as FormValidator<string | null>).set(day);\n onChange(day);\n };\n\n const handleSelect = (day: string | null) => {\n handleChange(day);\n onSelect(day);\n setIsPickerOpen(false);\n };\n\n const changeMonth = (delta: number) => {\n const index = currentYear * 12 + currentMonth - 1 + delta;\n const year = Math.floor(index / 12);\n // A day is written with four digits, so the calendar stops at the years it can name.\n if (year < 0 || year > 9999) return;\n setCurrentYear(year);\n setCurrentMonth((index % 12) + 1);\n };\n\n const tryParseDateString = (text: string): string | null => {\n const day = parseDateString(text);\n // `'YYYY-MM-DD'` sorts as it reads, so the bounds compare as plain strings.\n if (!day || (minDay && day < minDay) || (maxDay && day > maxDay)) return null;\n return day;\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n // A change that moved nothing needs no correcting, and re-running the day/month padding on\n // an unchanged value would fight the caret the mask just placed.\n if (nextState.value === previousState.value) return nextState;\n\n const corrected = correctDateMaskValue(nextState.value, previousState.value, nextState.selection ?? null);\n\n const parsed = tryParseDateString(corrected.value);\n if (parsed) handleChange(parsed);\n\n return corrected;\n };\n\n const getYearDropdownOptions = () => {\n let length = 400;\n let zeroOffset = getToday().year - 200;\n const min = parseDay(minDay);\n const max = parseDay(maxDay);\n if (min) zeroOffset = min.year;\n // Never negative: a `maxDate` before `minDate` made `Array(length)` throw during render.\n if (max) length = Math.max(0, max.year - zeroOffset + 1);\n return Array.from(Array(length).keys()).map((i) => ({ key: i + zeroOffset, label: i + zeroOffset }));\n };\n\n const currValue = getCurrValue();\n const hasErr = hasError();\n\n const header = noHeader ? null : (\n <div className={cx(styles.datePickerHeader, classNames?.header)} style={slotStyles?.header}>\n <ActionIcon icon={faChevronLeft} onClick={() => changeMonth(-1)} />\n <div className={styles.datePickerHeaderMonthAndYearContainer}>\n <div className={styles.datePickerHeaderMonthAndYear}>\n <Dropdown\n plainStyle\n scrollToSelected\n onChange={(v) => setCurrentMonth(v as number)}\n className={cx(styles.datePickerHeaderMonth, classNames?.monthDropdown)}\n style={slotStyles?.monthDropdown}\n value={getMonthName(getLocale('-'), currentYear, currentMonth, 1)}\n items={getMonthNames().map((month, index) => ({ key: index + 1, label: month }))}\n />\n <Dropdown\n plainStyle\n scrollToSelected\n useMatLabelStyle={false}\n className={cx(styles.datePickerHeaderYear, classNames?.yearDropdown)}\n style={slotStyles?.yearDropdown}\n onChange={(v) => setCurrentYear(v as number)}\n value={currentYear}\n items={getYearDropdownOptions()}\n />\n </div>\n </div>\n <ActionIcon icon={faChevronRight} onClick={() => changeMonth(1)} />\n </div>\n );\n\n const pickerContent = (\n <>\n {header}\n <DatePickerMonth\n className={cx(styles.datePickerMonth, classNames?.calendar)}\n style={slotStyles?.calendar}\n month={currentMonth}\n year={currentYear}\n onSelect={handleSelect}\n selectionStart={asDay(startDate) ?? currValue}\n selectionEnd={asDay(endDate) ?? currValue}\n minDate={minDay}\n maxDate={maxDay}\n onNavigateMonth={changeMonth}\n />\n {showClearButton && (\n <Button onClick={() => handleSelect(null)} className={classNames?.clearButton} style={slotStyles?.clearButton}>\n Clear\n </Button>\n )}\n {children}\n </>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n className={classNames?.input}\n style={slotStyles?.input}\n readOnly={isModal}\n classNames={isModal ? { input: styles.datePickerModalInput } : undefined}\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentDateString}\n onChange={(v) => setCurrentDateString(v as string)}\n onClick={() => setIsPickerOpen(true)}\n customInput={<MaskedInput mask='99.99.9999' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onBlur={() => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n // Only an edit is written back. A value the field cannot show, a leftover Date or a\n // timestamp, shows as empty, and writing that back would erase it on a mere tab-through.\n if (currentDateString !== getDateString(getCurrValue())) handleChange(tryParseDateString(currentDateString));\n }}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n isValid={!hasErr}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={(open: boolean) => setIsPickerOpen(open)}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n {...rest}\n className={cx(styles.datePicker, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{usePresentationDefault as t}from"../configProvider/usePresentationDefault.mjs";import{Presentation as n}from"../configProvider/presentation.types.mjs";import r from"../loading/spinnerLoading/index.mjs";import i from"../styles/sheet.module.mjs";import{PopoverAlign as ee,PopoverPlacement as te}from"../popover/popover.types.mjs";import ne from"../hooks/useSheet.mjs";import re from"../popover/popover.mjs";import ie from"../tooltip/tooltip.mjs";import{
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{usePresentationDefault as t}from"../configProvider/usePresentationDefault.mjs";import{Presentation as n}from"../configProvider/presentation.types.mjs";import r from"../loading/spinnerLoading/index.mjs";import i from"../styles/sheet.module.mjs";import{PopoverAlign as ee,PopoverPlacement as te}from"../popover/popover.types.mjs";import ne from"../hooks/useSheet.mjs";import re from"../popover/popover.mjs";import ie from"../tooltip/tooltip.mjs";import{edgeIndex as ae,nextIndex as oe,scrollOptionIntoView as se}from"../utils/listNavigation.mjs";import{useInfiniteScroll as ce}from"../infiniteBlock/useInfiniteScroll.mjs";import a from"./dropdown.module.mjs";import{useEffect as o,useId as le,useLayoutEffect as ue,useRef as s,useState as c}from"react";import l from"classnames";import{FontAwesomeIcon as de}from"@fortawesome/react-fontawesome";import{faChevronDown as fe}from"@fortawesome/free-solid-svg-icons";import{jsx as u,jsxs as d}from"react/jsx-runtime";var pe=500;function f(f){let{errorMessage:p=``,className:me=``,style:he,label:m=``,value:ge=``,isValid:_e=!0,tabIndex:ve=0,isRequired:ye=!1,customProps:h={},isRow:be=!1,disabled:g=!1,readOnly:_=!1,onScroll:xe=()=>Promise.resolve(),onClick:v,onChange:y,onFocus:Se=null,onBlur:Ce=null,onMouseEnter:we=null,onMouseLeave:Te=null,dropdownLabel:Ee,isDropdownListWider:b=!1,formValidator:x=null,classNames:S,styles:C,items:w=[],useMatLabelStyle:T=!0,alwaysFloatLabel:E=!1,placeholder:D=``,plainStyle:O=!1,scrollToSelected:De=!1,presentation:Oe,reactRef:ke,...Ae}=e(`Dropdown`,f),[je,Me]=c(!1),[Ne,Pe]=c(!1),[,Fe]=c(0),k=s(x),A=s(null),j=s(null),M=s(null),[Ie,Le]=c(!1),[N,P]=c(null),F=s({buffer:``,at:0}),I=le(),L=`${I}-listbox`,R=`${I}-label`,z=e=>`${I}-option-${e}`,B=!g&&!_,V=Ie&&B,{isLoading:Re,sentinelRef:ze}=ce(M,xe,!1),Be=t(),H=Oe??Be??n.Default,{isSheet:U}=ne(H);ue(()=>{let e=A.current,t=j.current;V&&!U&&e&&t&&(t.style.fontSize=window.getComputedStyle(e).fontSize)},[V,U]),o(()=>{if(k.current=x,!k.current)return;k.current.label=m??``,k.current.validate();let e=()=>Fe(e=>e+1);return k.current.registerOnUpdateListener(e),()=>k.current?.removeOnUpdateListener(e)},[x,m]);let W=x?x.value:ge,G=w.findIndex(e=>e.key===W);o(()=>{V&&N!==null&&se(M.current,document.getElementById(z(N)))},[V,N]);let Ve=e=>{Pe(!0),we?.(e)},He=e=>{Pe(!1),Te?.(e)},Ue=e=>{Me(!0),Se?.(e)},We=e=>{k.current&&(k.current.touched=!0),Me(!1),Ce?.(e)},Ge=()=>x?x.touched&&x.hasError():!_e||!!p,K=()=>!!(ye||x?.validators.find(e=>e.validatorId===`required`)),Ke=e=>{x?(x.set(e),y?.(x.value,h)):y?.(e,h)};function q(e){(!e||B)&&(Le(e),e?P(De&&G>=0?G:null):F.current={buffer:``,at:0})}function J(e){e.disabled||(Ke(e.key),q(!1))}let qe={isDisabled:e=>!!w[e].disabled};function Je(e){let t=Date.now(),n=t-F.current.at>pe?e:F.current.buffer+e;F.current={buffer:n,at:t};let r=n.toLowerCase(),i=w.findIndex(e=>!e.disabled&&typeof e.label==`string`&&e.label.toLowerCase().startsWith(r));i!==-1&&(V?P(i):J(w[i]))}function Ye(e){if(B){if(!V){e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `?(e.preventDefault(),q(!0)):e.key.length===1&&Je(e.key);return}if(e.key===`ArrowDown`||e.key===`ArrowUp`)e.preventDefault(),P(oe(N,e.key===`ArrowDown`?1:-1,w.length,qe));else if(e.key===`Home`||e.key===`End`)e.preventDefault(),P(ae(e.key===`Home`?`first`:`last`,w.length,qe));else if(e.key===`Enter`||e.key===` `){e.preventDefault();let t=N===null?void 0:w[N];t?J(t):q(!1)}else e.key===`Escape`||e.key===`Tab`?q(!1):e.key.length===1&&Je(e.key)}}let Y=Ee,X=Ge();w.forEach(e=>{e.key===W&&(Y=e.label)});let Z=Y||W,Q=Z==null||typeof Z==`string`&&Z.trim()===``,Xe=K()?u(`span`,{className:a.requiredMark,children:`*`}):null,Ze=m&&K()?`${m} *`:m,$=je&&!_;return d(`div`,{...Ae,className:l(me,S?.root,a.dropdownLabel,a.dropdown,{[a.dropdownLabelColumn]:!be}),style:{...he,...C?.root},onMouseEnter:Ve,onMouseLeave:He,children:[u(`div`,{children:u(re,{isOpen:V,onOpenChange:q,disabled:!B,placement:te.Bottom,align:ee.Start,offset:0,withArrow:!1,constrainWidth:!1,width:`trigger`,focusOnOpen:!1,presentation:H,classNames:{panel:a.dropdownPanel},content:u(`div`,{ref:j,className:l(!U&&a.dropdownInputListAnim,{[a.dropdownInputListAnimWider]:b&&!U}),children:d(`div`,{ref:M,id:L,role:`listbox`,"aria-label":m||D||void 0,className:l(a.dropdownInputList,U&&i.sheetScroll,S?.list),style:C?.list,children:[w.map((e,t)=>u(`div`,{id:z(t),role:`option`,"aria-selected":e.key===W,"aria-disabled":e.disabled||void 0,style:C?.option,className:l(a.dropdownInputListItem,S?.option,{[a.dropdownInputListItemActive]:N===t,[a.dropdownInputListItemSelected]:e.key===W,[a.dropdownInputListItemDisabled]:!!e.disabled}),onMouseDown:e=>e.preventDefault(),onMouseEnter:()=>P(t),onClick:()=>J(e),children:e.label},e.key)),u(`div`,{ref:ze,className:a.dropdownSentinel,"aria-hidden":`true`}),Re&&u(`div`,{className:a.dropdownLoadMore,"aria-hidden":`true`,children:u(r,{className:a.dropdownLoadMoreSpinner})})]})}),children:d(`div`,{ref:A,onFocus:Ue,onBlur:We,className:l(a.dropdownInput,{[a.dropdownInputPlain]:O,[a.dropdownInputReadOnly]:_&&!g},S?.field),style:C?.field,children:[u(`button`,{tabIndex:ve,type:`button`,disabled:g,role:`combobox`,"aria-haspopup":`listbox`,"aria-expanded":V,"aria-controls":L,"aria-activedescendant":V&&N!==null?z(N):void 0,"aria-labelledby":m?R:void 0,"aria-label":m?void 0:D||void 0,"aria-readonly":_||void 0,className:l(a.dropdownInputButton,{[a.dropdownInputButtonDisabled]:g,[a.dropdownInputButtonReadOnly]:_&&!g},S?.control),style:{...b?{padding:`6px`,border:`none`}:{},...C?.control},onKeyDown:Ye,onClick:v,ref:ke,children:Q?`\xA0`:Z}),u(`button`,{type:`button`,tabIndex:-1,disabled:g,"aria-hidden":`true`,className:l(a.dropdownInputButtonIcon,S?.icon),style:C?.icon,onMouseDown:e=>e.preventDefault(),onClick:v,children:!g&&!_&&u(de,{icon:fe,className:l(a.dropdownInputButtonIconArrow,{[a.dropdownInputButtonIconArrowOpen]:V})})}),u(`fieldset`,{className:l(a.dropdownFieldset,{[a.dropdownBorderPlain]:O,[a.dropdownBorderFocused]:$,[a.dropdownBorderInvalid]:X,[a.dropdownBorderError]:X}),children:u(`legend`,{className:l(a.dropdownFieldsetLegend,{[a.dropdownFieldsetLegendActive]:T&&(E||$||!Q)}),children:u(`span`,{children:Ze})})}),T&&m&&d(`div`,{id:R,className:l(a.dropdownMatLabel,{[a.dropdownMatLabelFloating]:E||$||!Q},S?.label),style:C?.label,children:[m,Xe]}),T&&D&&u(`div`,{className:l(a.dropdownPlaceholder,$&&!Y&&a.dropdownPlaceholderShown),children:D})]})})}),m&&!T&&d(`div`,{id:R,className:l(a.dropdownLabelText,S?.label),style:C?.label,children:[m,Xe]}),u(ie,{variant:`error`,message:x?x.getCurrentErrorMessage():p||``,isVisible:X&&(je||Ne)})]})}export{f as default};
|
|
2
2
|
//# sourceMappingURL=dropdown.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown.module.mjs","names":[],"sources":["../../../../package/common/dropdown/dropdown.module.pcss"],"sourcesContent":[".required-mark {\n padding: 0 0 0 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.dropdown {\n position: relative;\n\n /* Nothing inside gives the root a width, so as a flex or grid item it collapsed to the chevron\n and drew its border through the label. `input` and `multiSelect` say the same. */\n width: 100%;\n\n --dropdown-notch-height: 1.75em;\n\n /* See input.module.pcss for why this exists: the visible border lives on `-input`/`-fieldset`\n below, not this root, so a wrapping ButtonGroup's --group-radius-* custom properties (which\n inherit through any nesting depth, unlike border-radius itself) are what let this component\n flatten correctly when it sits inside a ButtonGroup. */\n --dropdown-radius: var(--group-radius-tl, var(--default-border-radius))\n var(--group-radius-tr, var(--default-border-radius)) var(--group-radius-br, var(--default-border-radius))\n var(--group-radius-bl, var(--default-border-radius));\n\n &-label {\n display: flex;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n white-space: nowrap;\n margin-right: 5px;\n margin-bottom: 5px;\n display: flex;\n align-items: center;\n color: var(--text-color);\n font-size: 12px;\n position: absolute;\n top: -15px;\n }\n }\n\n &-input {\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--input-background);\n border-radius: var(--dropdown-radius);\n\n &-plain {\n background: transparent;\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus-within {\n outline: none;\n }\n\n &-button {\n padding:
|
|
1
|
+
{"version":3,"file":"dropdown.module.mjs","names":[],"sources":["../../../../package/common/dropdown/dropdown.module.pcss"],"sourcesContent":[".required-mark {\n padding: 0 0 0 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.dropdown {\n position: relative;\n\n /* Nothing inside gives the root a width, so as a flex or grid item it collapsed to the chevron\n and drew its border through the label. `input` and `multiSelect` say the same. */\n width: 100%;\n\n --dropdown-notch-height: 1.75em;\n\n /* See input.module.pcss for why this exists: the visible border lives on `-input`/`-fieldset`\n below, not this root, so a wrapping ButtonGroup's --group-radius-* custom properties (which\n inherit through any nesting depth, unlike border-radius itself) are what let this component\n flatten correctly when it sits inside a ButtonGroup. */\n --dropdown-radius: var(--group-radius-tl, var(--default-border-radius))\n var(--group-radius-tr, var(--default-border-radius)) var(--group-radius-br, var(--default-border-radius))\n var(--group-radius-bl, var(--default-border-radius));\n\n &-label {\n display: flex;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n white-space: nowrap;\n margin-right: 5px;\n margin-bottom: 5px;\n display: flex;\n align-items: center;\n color: var(--text-color);\n font-size: 12px;\n position: absolute;\n top: -15px;\n }\n }\n\n &-input {\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--input-background);\n border-radius: var(--dropdown-radius);\n\n &-plain {\n background: transparent;\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus-within {\n outline: none;\n }\n\n &-button {\n padding: 8px 20% 6px 7.5px !important;\n background-color: transparent;\n border: none;\n font-family: inherit;\n font-size: inherit;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n text-align: left;\n width: 100%;\n line-height: 1.25;\n color: var(--text-color);\n\n &-disabled {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n border-radius: var(--dropdown-radius);\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus {\n outline: none;\n }\n\n &-icon {\n float: right;\n background-color: transparent;\n border: none;\n position: absolute;\n outline: none;\n right: var(--spacing-s);\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &-arrow {\n transition: transform 0.25s;\n pointer-events: none;\n\n &-open {\n transform: rotate(180deg);\n }\n }\n }\n }\n\n /* Chrome, placement and the portal come from the Popover this renders inside.\n What is left is the clipping that keeps the first and last row inside the\n panel's rounded corners. */\n &-list-anim {\n overflow: hidden;\n border-radius: inherit;\n\n &-wider {\n width: max-content !important;\n }\n }\n\n &-list {\n width: 100%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n max-height: 10em;\n list-style-type: none;\n\n &-item {\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--background-modal);\n padding: 0.5em;\n text-align: left;\n border-radius: 0;\n transition: background-color 0.3s;\n\n &-active {\n background-color: var(--background-accent);\n }\n\n &-selected {\n font-weight: 500;\n }\n\n &:focus {\n outline: none;\n }\n\n &:hover {\n background-color: var(--background-accent);\n }\n\n &-disabled {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n cursor: not-allowed;\n\n &:hover {\n background-color: var(--disabled-input-color);\n }\n }\n }\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n box-sizing: border-box;\n border-radius: var(--dropdown-radius);\n font-size: 0.8em;\n inset: calc(var(--dropdown-notch-height) / -2) 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-legend {\n display: block;\n\n /* Not taken from the text: an empty span gets no line box, which raised a label-less\n field's border half a notch. */\n height: var(--dropdown-notch-height);\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n line-height: var(--dropdown-notch-height);\n padding: 0 5px;\n opacity: 0;\n }\n\n /* With an empty label the span would still reserve its padding, leaving a gap in\n the fieldset's top border. Collapse it so the notch closes when there's no label. */\n span:empty {\n padding: 0;\n }\n }\n }\n\n &-placeholder {\n position: absolute;\n top: 50%;\n left: 7px;\n transform: translateY(-50%);\n transition: all 0.2s;\n opacity: 0;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n left: 7px;\n right: 0;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1em;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: 0 0 auto 14px;\n font-size: 0.8em;\n color: var(--input-label-floating-color, var(--text-color));\n transform: translateY(-50%);\n }\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 0.5;\n }\n }\n\n &-border {\n &-focused {\n outline-color: var(--focus-border-color, var(--primary-color));\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-plain:not(&-focused) {\n border-color: transparent;\n outline-color: transparent;\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n}\n\n/* The list brings its own padding and its rows reach the panel edge. */\n.dropdownPanel {\n padding: 0;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dropdown-matLabel,\n .dropdown-placeholder,\n .dropdown-input-button-icon-arrow {\n transition: none;\n }\n}\n\n/* The sentinel the infinite-scroll hook watches, and the spinner shown while a page loads.\n These came with `InfiniteBlock` when the list rendered through it; the list is its own scroll\n container now, so they live here. */\n.dropdown-sentinel {\n height: 1px;\n}\n\n.dropdown-load-more {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 4px 0;\n\n &-spinner {\n width: 32px;\n height: 32px;\n }\n}\n"],"mappings":""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import e from"../accordion/accordion.mjs";import
|
|
1
|
+
"use client";import e from"../accordion/accordion.mjs";import t from"../button/button.mjs";import n from"../copyButton/copyButton.mjs";import{showToast as r}from"../toast/toastService.mjs";import i from"./errorBoundary.module.mjs";import a from"react";import o from"classnames";import{FontAwesomeIcon as s}from"@fortawesome/react-fontawesome";import{faArrowRotateRight as c,faTriangleExclamation as l}from"@fortawesome/free-solid-svg-icons";import{jsx as u,jsxs as d}from"react/jsx-runtime";var f={stackTrace:`Stack trace`,copy:`Copy`,copied:`Copied`,reset:`Try again`,copySuccessToast:`Stack trace copied to clipboard`,copyErrorToast:`Could not copy stack trace`};function p(e,t){let n=[e.stack??`${e.name}: ${e.message}`];return t?.componentStack&&n.push(`Component stack:${t.componentStack}`),n.join(`
|
|
2
2
|
|
|
3
|
-
`)}var
|
|
3
|
+
`)}var m=class extends a.Component{constructor(...e){super(...e),this.state={error:null,errorInfo:null},this.reset=()=>{this.setState({error:null,errorInfo:null}),this.props.onReset?.()}}static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){this.setState({errorInfo:t}),this.props.onError?.(e,t)}componentDidUpdate(e){if(!this.state.error)return;let t=e.resetKeys??[],n=this.props.resetKeys??[];(n.length!==t.length||n.some((e,n)=>e!==t[n]))&&this.reset()}render(){let{error:a,errorInfo:m}=this.state,{children:h=null,title:g=`Something went wrong`,description:_,labels:v,fallback:y,hideStack:b=!1,className:x,style:S,classNames:C,styles:w,onError:T,onReset:E,resetKeys:D,role:O=`alert`,...k}=this.props;if(!a)return h;let A={...f,...v};return y?typeof y==`function`?y({error:a,errorInfo:m,resetErrorBoundary:this.reset}):y:d(`div`,{...k,role:O,className:o(i.errorBoundary,x,C?.root),style:{...S,...w?.root},children:[d(`div`,{className:o(i.errorBoundaryHeader,C?.header),style:w?.header,children:[u(`div`,{className:o(i.errorBoundaryBadge,C?.badge),style:w?.badge,children:u(s,{icon:l,className:o(i.errorBoundaryIcon,C?.icon),style:w?.icon})}),u(`div`,{className:o(i.errorBoundaryTitle,C?.title),style:w?.title,children:g}),u(`div`,{className:o(i.errorBoundaryDescription,C?.description),style:w?.description,children:_??a.message})]}),!b&&d(e,{title:A.stackTrace,className:o(i.errorBoundaryStack,C?.stack),style:w?.stack,children:[d(`div`,{className:o(i.errorBoundaryStackHeader,C?.stackHeader),style:w?.stackHeader,children:[u(`span`,{className:o(i.errorBoundaryStackLabel,C?.stackLabel),style:w?.stackLabel,children:a.name||`Error`}),u(n,{value:p(a,m),labels:{copy:A.copy,copied:A.copied},onCopy:()=>r(A.copySuccessToast,{type:`success`}),onError:()=>r(A.copyErrorToast,{type:`error`}),className:o(i.errorBoundaryCopyButton,C?.copyButton),style:w?.copyButton})]}),u(`pre`,{className:o(i.errorBoundaryStackTrace,C?.stackTrace),style:w?.stackTrace,children:p(a,m)})]}),u(`div`,{className:o(i.errorBoundaryActions,C?.actions),style:w?.actions,children:u(t,{onClick:this.reset,icon:c,className:o(i.errorBoundaryResetButton,C?.resetButton),style:w?.resetButton,children:A.reset})})]})}};export{m as default};
|
|
4
4
|
//# sourceMappingURL=errorBoundary.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorBoundary.mjs","names":[],"sources":["../../../../package/common/errorBoundary/errorBoundary.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faTriangleExclamation,
|
|
1
|
+
{"version":3,"file":"errorBoundary.mjs","names":[],"sources":["../../../../package/common/errorBoundary/errorBoundary.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faTriangleExclamation, faArrowRotateRight } from '@fortawesome/free-solid-svg-icons';\n\nimport Button from '../button';\nimport Accordion from '../accordion';\nimport { showToast } from '../toast';\nimport CopyButton from '../copyButton';\nimport type { ErrorBoundaryLabels, ErrorBoundaryProps, ErrorBoundaryState } from './errorBoundary.types';\nimport styles from './errorBoundary.module.pcss';\n\nconst DEFAULT_LABELS: Required<ErrorBoundaryLabels> = {\n stackTrace: 'Stack trace',\n copy: 'Copy',\n copied: 'Copied',\n reset: 'Try again',\n copySuccessToast: 'Stack trace copied to clipboard',\n copyErrorToast: 'Could not copy stack trace',\n};\n\nfunction formatStackTrace(error: Error, errorInfo: React.ErrorInfo | null): string {\n const parts = [error.stack ?? `${error.name}: ${error.message}`];\n if (errorInfo?.componentStack) parts.push(`Component stack:${errorInfo.componentStack}`);\n return parts.join('\\n\\n');\n}\n\nclass ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState = { error: null, errorInfo: null };\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return { error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.setState({ errorInfo });\n this.props.onError?.(error, errorInfo);\n }\n\n componentDidUpdate(prevProps: ErrorBoundaryProps): void {\n if (!this.state.error) return;\n const prevKeys = prevProps.resetKeys ?? [];\n const nextKeys = this.props.resetKeys ?? [];\n const changed = nextKeys.length !== prevKeys.length || nextKeys.some((key, i) => key !== prevKeys[i]);\n if (changed) this.reset();\n }\n\n private reset = (): void => {\n this.setState({ error: null, errorInfo: null });\n this.props.onReset?.();\n };\n\n render(): React.ReactNode {\n const { error, errorInfo } = this.state;\n // onError/onReset/resetKeys are consumed elsewhere (getDerivedStateFromError,\n // componentDidCatch, componentDidUpdate) and must not land on the root element via `rest`.\n /* eslint-disable @typescript-eslint/no-unused-vars */\n const {\n children = null,\n title = 'Something went wrong',\n description,\n labels: labelOverrides,\n fallback,\n hideStack = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n onError,\n onReset,\n resetKeys,\n role = 'alert',\n ...rest\n } = this.props;\n\n if (!error) return children;\n\n const labels = { ...DEFAULT_LABELS, ...labelOverrides };\n\n if (fallback) {\n return typeof fallback === 'function' ? fallback({ error, errorInfo, resetErrorBoundary: this.reset }) : fallback;\n }\n\n return (\n <div\n {...rest}\n role={role}\n className={cx(styles.errorBoundary, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div className={cx(styles.errorBoundaryHeader, classNames?.header)} style={slotStyles?.header}>\n <div className={cx(styles.errorBoundaryBadge, classNames?.badge)} style={slotStyles?.badge}>\n <FontAwesomeIcon\n icon={faTriangleExclamation}\n className={cx(styles.errorBoundaryIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </div>\n <div className={cx(styles.errorBoundaryTitle, classNames?.title)} style={slotStyles?.title}>\n {title}\n </div>\n <div className={cx(styles.errorBoundaryDescription, classNames?.description)} style={slotStyles?.description}>\n {description ?? error.message}\n </div>\n </div>\n\n {!hideStack && (\n <Accordion\n title={labels.stackTrace}\n className={cx(styles.errorBoundaryStack, classNames?.stack)}\n style={slotStyles?.stack}\n >\n <div\n className={cx(styles.errorBoundaryStackHeader, classNames?.stackHeader)}\n style={slotStyles?.stackHeader}\n >\n <span\n className={cx(styles.errorBoundaryStackLabel, classNames?.stackLabel)}\n style={slotStyles?.stackLabel}\n >\n {error.name || 'Error'}\n </span>\n <CopyButton\n value={formatStackTrace(error, errorInfo)}\n labels={{ copy: labels.copy, copied: labels.copied }}\n onCopy={() => showToast(labels.copySuccessToast, { type: 'success' })}\n onError={() => showToast(labels.copyErrorToast, { type: 'error' })}\n className={cx(styles.errorBoundaryCopyButton, classNames?.copyButton)}\n style={slotStyles?.copyButton}\n />\n </div>\n <pre className={cx(styles.errorBoundaryStackTrace, classNames?.stackTrace)} style={slotStyles?.stackTrace}>\n {formatStackTrace(error, errorInfo)}\n </pre>\n </Accordion>\n )}\n\n <div className={cx(styles.errorBoundaryActions, classNames?.actions)} style={slotStyles?.actions}>\n <Button\n onClick={this.reset}\n icon={faArrowRotateRight}\n className={cx(styles.errorBoundaryResetButton, classNames?.resetButton)}\n style={slotStyles?.resetButton}\n >\n {labels.reset}\n </Button>\n </div>\n </div>\n );\n }\n}\n\nexport default ErrorBoundary;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e=`errorBoundary_XdPM0`,t=`errorBoundaryHeader_2PdRz`,n=`errorBoundaryBadge_TyXdO`,r=`errorBoundaryBadgeIn_Q-MMB`,i=`errorBoundaryIcon_PcZ4H`,a=`errorBoundaryTitle_X9tEE`,o=`errorBoundaryFadeUp_2qx5d`,s=`errorBoundaryDescription_NELdD`,c=`errorBoundaryStack_BUkBD`,l=`errorBoundaryStackHeader_uimLH`,u=`errorBoundaryStackLabel_D-19W`,d=`errorBoundaryCopyButton_e09KC`,f=`
|
|
1
|
+
"use client";var e=`errorBoundary_XdPM0`,t=`errorBoundaryHeader_2PdRz`,n=`errorBoundaryBadge_TyXdO`,r=`errorBoundaryBadgeIn_Q-MMB`,i=`errorBoundaryIcon_PcZ4H`,a=`errorBoundaryTitle_X9tEE`,o=`errorBoundaryFadeUp_2qx5d`,s=`errorBoundaryDescription_NELdD`,c=`errorBoundaryStack_BUkBD`,l=`errorBoundaryStackHeader_uimLH`,u=`errorBoundaryStackLabel_D-19W`,d=`errorBoundaryCopyButton_e09KC`,f=`errorBoundaryStackTrace_DskzG`,p=`errorBoundaryActions_h3GMQ`,m={errorBoundary:e,errorBoundaryHeader:t,errorBoundaryBadge:n,errorBoundaryBadgeIn:r,errorBoundaryIcon:i,errorBoundaryTitle:a,errorBoundaryFadeUp:o,errorBoundaryDescription:s,errorBoundaryStack:c,errorBoundaryStackHeader:l,errorBoundaryStackLabel:u,errorBoundaryCopyButton:d,errorBoundaryStackTrace:f,errorBoundaryActions:p};export{m as default,e as errorBoundary,p as errorBoundaryActions,n as errorBoundaryBadge,r as errorBoundaryBadgeIn,d as errorBoundaryCopyButton,s as errorBoundaryDescription,o as errorBoundaryFadeUp,t as errorBoundaryHeader,i as errorBoundaryIcon,c as errorBoundaryStack,l as errorBoundaryStackHeader,u as errorBoundaryStackLabel,f as errorBoundaryStackTrace,a as errorBoundaryTitle};
|
|
2
2
|
//# sourceMappingURL=errorBoundary.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorBoundary.module.mjs","names":[],"sources":["../../../../package/common/errorBoundary/errorBoundary.module.pcss"],"sourcesContent":["@keyframes errorBoundaryBadgeIn {\n from {\n opacity: 0;\n transform: scale(0.6);\n }\n\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes errorBoundaryFadeUp {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.errorBoundary {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n padding: 36px 28px;\n border-radius: var(--default-border-radius);\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n box-shadow: var(--card-shadow);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n overflow: hidden;\n isolation: isolate;\n\n &::before {\n content: '';\n position: absolute;\n top: -30px;\n left: 50%;\n width: 260px;\n height: 180px;\n transform: translateX(-50%);\n background: radial-gradient(closest-side, color-mix(in srgb, var(--error-color) 16%, transparent), transparent);\n pointer-events: none;\n z-index: -1;\n }\n\n &Header {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n text-align: center;\n max-width: 420px;\n }\n\n &Badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 52px;\n height: 52px;\n border-radius: 50%;\n background: var(--error-lighter);\n box-shadow: 0 0 0 6px color-mix(in srgb, var(--error-color) 8%, transparent);\n margin-bottom: 4px;\n animation: errorBoundaryBadgeIn 0.35s ease-out;\n }\n\n &Icon {\n font-size: 20px;\n color: var(--error-color, #ef4444);\n }\n\n &Title {\n font-weight: var(--header-font-weight, 700);\n font-size: 17px;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.05s backwards;\n }\n\n &Description {\n color: var(--text-dark);\n font-size: 14px;\n line-height: 1.5;\n word-break: break-word;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.1s backwards;\n }\n\n &Stack {\n align-self: stretch;\n width: 100%;\n text-align: left;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.15s backwards;\n }\n\n &StackHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 10px;\n }\n\n &StackLabel {\n font-family: var(--monospace-font, monospace);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--error-color, #ef4444);\n background: var(--error-lighter);\n padding: 3px 8px;\n border-radius: 999px;\n }\n\n &CopyButton {\n flex-shrink: 0;\n
|
|
1
|
+
{"version":3,"file":"errorBoundary.module.mjs","names":[],"sources":["../../../../package/common/errorBoundary/errorBoundary.module.pcss"],"sourcesContent":["@keyframes errorBoundaryBadgeIn {\n from {\n opacity: 0;\n transform: scale(0.6);\n }\n\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes errorBoundaryFadeUp {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.errorBoundary {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n padding: 36px 28px;\n border-radius: var(--default-border-radius);\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n box-shadow: var(--card-shadow);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n overflow: hidden;\n isolation: isolate;\n\n &::before {\n content: '';\n position: absolute;\n top: -30px;\n left: 50%;\n width: 260px;\n height: 180px;\n transform: translateX(-50%);\n background: radial-gradient(closest-side, color-mix(in srgb, var(--error-color) 16%, transparent), transparent);\n pointer-events: none;\n z-index: -1;\n }\n\n &Header {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n text-align: center;\n max-width: 420px;\n }\n\n &Badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 52px;\n height: 52px;\n border-radius: 50%;\n background: var(--error-lighter);\n box-shadow: 0 0 0 6px color-mix(in srgb, var(--error-color) 8%, transparent);\n margin-bottom: 4px;\n animation: errorBoundaryBadgeIn 0.35s ease-out;\n }\n\n &Icon {\n font-size: 20px;\n color: var(--error-color, #ef4444);\n }\n\n &Title {\n font-weight: var(--header-font-weight, 700);\n font-size: 17px;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.05s backwards;\n }\n\n &Description {\n color: var(--text-dark);\n font-size: 14px;\n line-height: 1.5;\n word-break: break-word;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.1s backwards;\n }\n\n &Stack {\n align-self: stretch;\n width: 100%;\n text-align: left;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.15s backwards;\n }\n\n &StackHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 10px;\n }\n\n &StackLabel {\n font-family: var(--monospace-font, monospace);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--error-color, #ef4444);\n background: var(--error-lighter);\n padding: 3px 8px;\n border-radius: 999px;\n }\n\n &CopyButton {\n flex-shrink: 0;\n }\n\n &StackTrace {\n margin: 0;\n padding: 12px;\n border-radius: var(--default-border-radius);\n background: var(--background);\n color: var(--text-dark);\n font-family: var(--monospace-font, monospace);\n font-size: 12px;\n line-height: 1.6;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 320px;\n overflow: auto;\n }\n\n &Actions {\n display: flex;\n justify-content: center;\n animation: errorBoundaryFadeUp 0.3s ease-out 0.2s backwards;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .errorBoundaryBadge,\n .errorBoundaryTitle,\n .errorBoundaryDescription,\n .errorBoundaryStack,\n .errorBoundaryActions {\n animation: none;\n }\n}\n"],"mappings":""}
|