minerva-design 1.19.0 → 1.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/angular/fesm2022/minerva-angular.mjs +10 -14
- package/dist/angular/fesm2022/minerva-angular.mjs.map +1 -1
- package/dist/angular/types/minerva-angular.d.ts +8 -2
- package/dist/core/decimal-places.d.cts +6 -0
- package/dist/core/decimal-places.d.ts +6 -0
- package/dist/core/index.cjs +21 -21
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +590 -580
- package/dist/core/index.js.map +1 -1
- package/dist/core/keyboard-navigation.d.cts +14 -0
- package/dist/core/keyboard-navigation.d.ts +14 -0
- package/dist/core/number-input.d.cts +4 -1
- package/dist/core/number-input.d.ts +4 -1
- package/dist/core/slider.d.cts +1 -1
- package/dist/core/slider.d.ts +1 -1
- package/dist/react/components/AutoComplete/AutoComplete.cjs +1 -1
- package/dist/react/components/AutoComplete/AutoComplete.cjs.map +1 -1
- package/dist/react/components/AutoComplete/AutoComplete.js +91 -90
- package/dist/react/components/AutoComplete/AutoComplete.js.map +1 -1
- package/dist/react/components/DatePicker/DatePicker.cjs +1 -1
- package/dist/react/components/DatePicker/DatePicker.cjs.map +1 -1
- package/dist/react/components/DatePicker/DatePicker.js +3 -2
- package/dist/react/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/vue/components/AutoComplete/AutoComplete.vue.js.map +1 -1
- package/dist/vue/components/AutoComplete/AutoComplete.vue_vue_type_script_setup_true_lang.js +58 -57
- package/dist/vue/components/AutoComplete/AutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/weapp/controls.js +24 -12
- package/dist/web-components/cdn/minerva.js +532 -532
- package/dist/web-components/cdn/minerva.js.map +1 -1
- package/dist/web-components/components/autocomplete/autocomplete.d.ts +7 -1
- package/dist/web-components/components/autocomplete/autocomplete.js +29 -24
- package/dist/web-components/components/autocomplete/autocomplete.js.map +1 -1
- package/dist/web-components/components/date-picker/date-picker.js +11 -5
- package/dist/web-components/components/date-picker/date-picker.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoComplete.js","names":["styles","ProgressIndicator","_Fragment","Empty","ProgressIndicator_default","Empty_default","autoComplete_module_default","React","Fragment$1","DEFAULT_OFFSET","EMPTY_OPTIONS","PLACEMENT","AutoComplete","defaultValueProp","inputValue","setInputValue","useControllableState","visible","setVisible","onDropdownVisibleChange","focusedIndex","setFocusedIndex","useState","hoveredIndex","setHoveredIndex","container","setContainer","input","setInput","setInputRef","useMergedRefs","ref","dropdown","setDropdown","vertical","placement","baseId","useId","listboxId","composing","useRef","field","useFormControlProps","inputProps","inputId","blocked","warnControlledProps","onChange","shown","open","close","processedOptions","useMemo","search","result","options","filterOption","option","sortOption","groupedOptions","groupBy","groupMode","runs","group","last","groups","list","navigableOptions","activeIndex","autoHighlight","moveFocus","count","index","step","i","handleOptionSelect","fillOnSelect","onSelect","handleKeyDown","event","onSubmit","handleInputChange","next","handleBlur","handleOptionClick","onOptionClick","activeOptionId","ESCAPE_CONSUMER_ATTRIBUTE","reopenRef","useEffect","onClick","renderBasicOption","renderOptionItem","active","highlighted","cn","hooks","mode","renderOption","className","label","Input","FloatingPanel","offset","dropdownClassName","animation","loading","groupOptions","groupIndex","renderEmpty","emptyProps"],"sources":["../../../../../react/src/components/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Input } from \"../Input\";\nimport { ProgressIndicator } from \"../ProgressIndicator\";\nimport { Empty } from \"../Empty\";\nimport type { AutoCompleteProps, AutoCompleteOption } from \"./types\";\nimport { FloatingPanel } from \"../../internal/FloatingPanel\";\nimport { useControllableState } from \"../../internal/useControllableState\";\nimport { warnControlledProps } from \"../../internal/devWarnings\";\nimport { useMergedRefs } from \"../../internal/mergeRefs\";\nimport { useFormControlProps } from \"../FormControl/context\";\nimport { hooks } from \"../../internal/stylingHooks\";\nimport styles from \"./autoComplete.module.scss\";\nimport { ESCAPE_CONSUMER_ATTRIBUTE } from \"@minerva/dom\";\n\nconst DEFAULT_OFFSET = Object.freeze({ x: 0, y: 4 });\nconst EMPTY_OPTIONS: AutoCompleteOption[] = [];\n\nconst PLACEMENT = {\n top: \"top-start\",\n bottom: \"bottom-start\",\n left: \"left-start\",\n right: \"right-start\",\n} as const;\n\n/**\n * AutoComplete: a text input (combobox) that suggests options from a list.\n * Supports grouping, custom rendering and async loading; the input text can\n * be controlled or not. Focus stays in the input (`aria-activedescendant`).\n * For picking several values use `TagInput`.\n */\nconst AutoComplete = ({\n ref,\n name,\n label,\n mode = \"basic\",\n value,\n onChange,\n options = EMPTY_OPTIONS,\n defaultValue: defaultValueProp,\n onSelect,\n filterOption,\n groupBy,\n renderOption,\n renderEmpty,\n loading = false,\n inputProps,\n emptyProps,\n placement = \"bottom\",\n offset = DEFAULT_OFFSET,\n animation = true,\n sortOption,\n onOptionClick,\n onDropdownVisibleChange,\n dropdownClassName,\n onSubmit,\n autoHighlight = false,\n fillOnSelect = true,\n className,\n groupMode = \"first\",\n}: AutoCompleteProps) => {\n const [inputValue, setInputValue] = useControllableState({\n value,\n defaultValue: defaultValueProp ?? \"\",\n onChange,\n name: \"AutoComplete\",\n });\n const [visible, setVisible] = useControllableState({\n defaultValue: false,\n onChange: onDropdownVisibleChange,\n name: \"AutoComplete\",\n prop: \"open\",\n });\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const [hoveredIndex, setHoveredIndex] = useState(-1);\n const [container, setContainer] = useState<HTMLDivElement | null>(null);\n const [input, setInput] = useState<HTMLInputElement | null>(null);\n const setInputRef = useMergedRefs<HTMLInputElement>(setInput, ref);\n const [dropdown, setDropdown] = useState<HTMLDivElement | null>(null);\n const vertical = placement === \"top\" || placement === \"bottom\";\n\n const baseId = useId();\n const listboxId = `${baseId}-listbox`;\n // IME composition in progress: Enter / arrows belong to the IME.\n const composing = useRef(false);\n\n // FormControl wiring (id, disabled / read-only state, aria-*). The\n // input's own disabled / readOnly props still apply.\n const field = useFormControlProps({\n id: inputProps?.id,\n disabled: inputProps?.disabled,\n readOnly: inputProps?.readOnly,\n });\n const inputId = field.id ?? `${baseId}-input`;\n const blocked = !!field.disabled || !!field.readOnly;\n if (process.env.NODE_ENV !== \"production\") {\n warnControlledProps(\"AutoComplete\", {\n prop: \"value\",\n value,\n defaultProp: \"defaultValue\",\n defaultValue: defaultValueProp,\n handlerProp: \"onChange\",\n handler: onChange,\n locked: blocked,\n lockHint: \"set `inputProps.disabled` / `inputProps.readOnly`\",\n });\n }\n // A disabled / read-only field never shows (or keeps) the dropdown.\n const shown = visible && !blocked;\n\n const open = () => {\n if (!blocked) setVisible(true);\n };\n const close = () => {\n setVisible(false);\n setFocusedIndex(-1);\n };\n\n const processedOptions = useMemo(() => {\n const search = inputValue.toLowerCase();\n const result = options.filter((option) =>\n filterOption\n ? filterOption(inputValue, option)\n : option.label.toLowerCase().includes(search),\n );\n return sortOption ? [...result].sort(sortOption) : result;\n }, [options, inputValue, filterOption, sortOption]);\n\n /** Groups in order of first appearance, or runs of adjacent options */\n const groupedOptions = useMemo(() => {\n if (!groupBy) return null;\n if (groupMode === \"adjacent\") {\n const runs: [string, AutoCompleteOption[]][] = [];\n processedOptions.forEach((option) => {\n const group = groupBy(option);\n const last = runs[runs.length - 1];\n if (last && last[0] === group) last[1].push(option);\n else runs.push([group, [option]]);\n });\n return runs;\n }\n const groups = new Map<string, AutoCompleteOption[]>();\n processedOptions.forEach((option) => {\n const group = groupBy(option);\n const list = groups.get(group);\n if (list) list.push(option);\n else groups.set(group, [option]);\n });\n return Array.from(groups.entries());\n }, [processedOptions, groupBy, groupMode]);\n\n /** Options in display order; keyboard / hover indexes refer to this list */\n const navigableOptions = useMemo(\n () =>\n groupedOptions\n ? groupedOptions.flatMap(([, list]) => list)\n : processedOptions,\n [groupedOptions, processedOptions],\n );\n\n // With autoHighlight the first enabled option is active until the user\n // moves the highlight.\n const activeIndex =\n focusedIndex >= 0\n ? focusedIndex\n : autoHighlight && shown\n ? navigableOptions.findIndex((option) => !option.disabled)\n : -1;\n\n const moveFocus = (step: 1 | -1) => {\n const count = navigableOptions.length;\n if (count === 0) return;\n // from \"nothing focused\", ArrowDown starts at the first option and\n // ArrowUp at the last one\n let index = activeIndex >= 0 ? activeIndex : step === 1 ? -1 : count;\n for (let i = 0; i < count; i += 1) {\n index = (index + step + count) % count;\n if (!navigableOptions[index].disabled) {\n setFocusedIndex(index);\n return;\n }\n }\n };\n\n const handleOptionSelect = (option: AutoCompleteOption) => {\n if (option.disabled) return;\n if (fillOnSelect) setInputValue(option.label);\n close();\n onSelect?.(option);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (\n blocked ||\n composing.current ||\n event.nativeEvent.isComposing ||\n event.keyCode === 229\n )\n return;\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!visible) open();\n moveFocus(1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!visible) open();\n moveFocus(-1);\n break;\n case \"Enter\": {\n const option = shown ? navigableOptions[activeIndex] : undefined;\n if (option) {\n event.preventDefault();\n handleOptionSelect(option);\n } else if (onSubmit && inputValue.trim()) {\n // No active option: submit the typed text (e.g. a search).\n event.preventDefault();\n onSubmit(inputValue.trim());\n close();\n }\n break;\n }\n case \"Escape\":\n // Open: the dropdown's dismissable layer closes it (topmost only).\n // Closed: clears the text (APG combobox), `onChange(\"\")`.\n if (!shown && inputValue !== \"\") {\n event.preventDefault();\n setInputValue(\"\");\n setFocusedIndex(-1);\n }\n break;\n default:\n break;\n }\n };\n\n const handleInputChange = (next: string) => {\n setInputValue(next);\n setFocusedIndex(-1);\n open();\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n const next = event.relatedTarget as Node | null;\n if (next && (dropdown?.contains(next) || container?.contains(next))) return;\n close();\n };\n\n const handleOptionClick = (option: AutoCompleteOption) => {\n if (option.disabled || composing.current) return;\n handleOptionSelect(option);\n onOptionClick?.(option);\n input?.focus();\n };\n\n // Expose combobox semantics on the inner <input>\n const activeOptionId =\n shown && activeIndex >= 0\n ? `${listboxId}-option-${activeIndex}`\n : undefined;\n useEffect(() => {\n if (!input) return;\n input.setAttribute(\"role\", \"combobox\");\n input.setAttribute(\"aria-autocomplete\", \"list\");\n input.setAttribute(\"aria-expanded\", String(shown));\n // Closed with text: Escape clears it instead of closing an enclosing\n // Modal / Drawer / Popover\n if (!shown && inputValue !== \"\") {\n input.setAttribute(ESCAPE_CONSUMER_ATTRIBUTE, \"\");\n } else input.removeAttribute(ESCAPE_CONSUMER_ATTRIBUTE);\n if (shown) input.setAttribute(\"aria-controls\", listboxId);\n else input.removeAttribute(\"aria-controls\");\n if (activeOptionId)\n input.setAttribute(\"aria-activedescendant\", activeOptionId);\n else input.removeAttribute(\"aria-activedescendant\");\n }, [input, shown, listboxId, activeOptionId, inputValue]);\n\n // Clicking the still-focused input (after a pick or Escape) reopens the\n // dropdown; focus alone does not fire again.\n const reopenRef = useRef(() => {});\n useEffect(() => {\n reopenRef.current = () => {\n if (!visible) open();\n };\n });\n useEffect(() => {\n if (!input) return;\n const onClick = () => reopenRef.current();\n input.addEventListener(\"click\", onClick);\n return () => input.removeEventListener(\"click\", onClick);\n }, [input]);\n\n // Keep the keyboard-focused option scrolled into view\n useEffect(() => {\n if (!activeOptionId) return;\n document\n .getElementById(activeOptionId)\n ?.scrollIntoView?.({ block: \"nearest\" });\n }, [activeOptionId]);\n\n const renderBasicOption = (option: AutoCompleteOption) => (\n <div className={styles.basicOption}>\n {option.icon && <span className={styles.icon}>{option.icon}</span>}\n <div className={styles.content}>\n <div className={styles.label}>{option.label}</div>\n {option.description && (\n <div className={styles.description}>{option.description}</div>\n )}\n </div>\n </div>\n );\n\n const renderOptionItem = (option: AutoCompleteOption, index: number) => {\n const active = activeIndex === index;\n const highlighted = hoveredIndex === index || active;\n return (\n <div\n key={option.value}\n className={cn(styles.optionItem, {\n [styles.disabled]: option.disabled,\n [styles.highlight]: option.highlight,\n [styles.active]: highlighted,\n })}\n style={option.style}\n role=\"option\"\n // Focus stays in the input (aria-activedescendant); -1 keeps the\n // option out of the tab order while making it programmatically\n // focusable.\n tabIndex={-1}\n id={`${listboxId}-option-${index}`}\n aria-selected={active}\n aria-disabled={option.disabled || undefined}\n // keep focus (and the open dropdown) in the input while clicking\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleOptionClick(option)}\n onKeyDown={(e) => {\n if (e.key !== \"Enter\" && e.key !== \" \") return;\n e.preventDefault();\n handleOptionClick(option);\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(-1)}\n {...hooks(\"autocomplete\", \"item\", {\n highlighted,\n disabled: option.disabled,\n })}\n >\n {mode === \"custom\" && renderOption\n ? renderOption(option)\n : renderBasicOption(option)}\n </div>\n );\n };\n\n return (\n <div\n ref={setContainer}\n className={cn(styles.autoComplete, className)}\n onCompositionStart={() => {\n composing.current = true;\n }}\n onCompositionEnd={() => {\n composing.current = false;\n }}\n {...hooks(\"autocomplete\", \"root\", {\n state: shown ? \"open\" : \"closed\",\n disabled: !!field.disabled,\n readonly: !!field.readOnly,\n loading,\n })}\n >\n {label && (\n <label\n htmlFor={inputId}\n className={styles.label}\n {...hooks(\"autocomplete\", \"label\")}\n >\n {label}\n </label>\n )}\n <Input\n {...inputProps}\n id={inputId}\n disabled={field.disabled}\n readOnly={field.readOnly}\n name={name}\n ref={setInputRef}\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n onFocus={(e) => {\n open();\n inputProps?.onFocus?.(e);\n }}\n onBlur={(e) => {\n handleBlur(e);\n inputProps?.onBlur?.(e);\n }}\n onKeyDown={(e) => {\n handleKeyDown(e);\n inputProps?.onKeyDown?.(e);\n }}\n />\n\n <FloatingPanel\n ref={setDropdown}\n open={shown}\n anchor={container}\n placement={PLACEMENT[placement]}\n offset={{\n mainAxis: vertical ? offset.y : offset.x,\n crossAxis: vertical ? offset.x : offset.y,\n }}\n matchAnchorWidth=\"min\"\n // the field (label, input, suffix) is part of the dropdown layer\n branches={() => [container]}\n onEscapeKeyDown={(event) => {\n // Escape during IME composition cancels the composition only\n if (composing.current || event.isComposing) event.preventDefault();\n }}\n onDismiss={close}\n returnFocusOnEscape={() => input}\n className={cn(styles.popup, dropdownClassName)}\n {...hooks(\"autocomplete\", \"content\", { state: \"open\" })}\n >\n <div className={cn(styles.dropdown, animation && styles.animated)}>\n {/* While open the listbox always exists (aria-controls target);\n loading / empty states are presentational rows inside it. */}\n <div\n className={styles.optionList}\n role=\"listbox\"\n id={listboxId}\n aria-label={label}\n aria-busy={loading || undefined}\n {...hooks(\"autocomplete\", \"list\")}\n >\n {loading ? (\n <div\n role=\"presentation\"\n className={styles.loading}\n {...hooks(\"autocomplete\", \"loading\")}\n >\n <ProgressIndicator />\n </div>\n ) : processedOptions.length > 0 ? (\n <>\n {groupedOptions\n ? groupedOptions.map(([group, groupOptions], groupIndex) =>\n group === \"\" ? (\n // ungrouped options: no heading\n <React.Fragment key={`${groupIndex}-`}>\n {groupOptions.map((option) =>\n renderOptionItem(\n option,\n navigableOptions.indexOf(option),\n ),\n )}\n </React.Fragment>\n ) : (\n <div\n key={`${groupIndex}-${group}`}\n className={styles.optionGroup}\n role=\"group\"\n aria-label={group}\n >\n <div\n className={styles.groupLabel}\n aria-hidden=\"true\"\n {...hooks(\"autocomplete\", \"group-label\")}\n >\n {group}\n </div>\n {groupOptions.map((option) =>\n renderOptionItem(\n option,\n navigableOptions.indexOf(option),\n ),\n )}\n </div>\n ),\n )\n : processedOptions.map((option, index) =>\n renderOptionItem(option, index),\n )}\n </>\n ) : (\n <div\n role=\"presentation\"\n className={styles.empty}\n {...hooks(\"autocomplete\", \"empty\")}\n >\n {renderEmpty?.() || <Empty {...emptyProps} />}\n </div>\n )}\n </div>\n </div>\n </FloatingPanel>\n </div>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AutoComplete.js","names":["styles","ProgressIndicator","_Fragment","Empty","ProgressIndicator_default","Empty_default","autoComplete_module_default","React","Fragment$1","DEFAULT_OFFSET","EMPTY_OPTIONS","PLACEMENT","AutoComplete","defaultValueProp","inputValue","setInputValue","useControllableState","visible","setVisible","onDropdownVisibleChange","focusedValue","setFocusedValue","useState","hoveredIndex","setHoveredIndex","container","setContainer","input","setInput","setInputRef","useMergedRefs","ref","dropdown","setDropdown","vertical","placement","baseId","useId","listboxId","composing","useRef","field","useFormControlProps","inputProps","inputId","blocked","warnControlledProps","onChange","shown","open","close","processedOptions","useMemo","search","result","options","filterOption","option","sortOption","groupedOptions","groupBy","groupMode","runs","group","last","groups","list","navigableOptions","interactiveOptions","loading","activeIndex","resolveActiveOptionIndex","autoHighlight","moveFocus","count","index","step","i","handleOptionSelect","fillOnSelect","onSelect","handleKeyDown","event","onSubmit","handleInputChange","next","handleBlur","handleOptionClick","onOptionClick","activeOptionId","ESCAPE_CONSUMER_ATTRIBUTE","reopenRef","useEffect","onClick","renderBasicOption","renderOptionItem","active","highlighted","cn","hooks","mode","renderOption","className","label","Input","FloatingPanel","offset","dropdownClassName","animation","groupOptions","groupIndex","renderEmpty","emptyProps"],"sources":["../../../../../react/src/components/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Input } from \"../Input\";\nimport { ProgressIndicator } from \"../ProgressIndicator\";\nimport { Empty } from \"../Empty\";\nimport type { AutoCompleteProps, AutoCompleteOption } from \"./types\";\nimport { FloatingPanel } from \"../../internal/FloatingPanel\";\nimport { useControllableState } from \"../../internal/useControllableState\";\nimport { warnControlledProps } from \"../../internal/devWarnings\";\nimport { useMergedRefs } from \"../../internal/mergeRefs\";\nimport { useFormControlProps } from \"../FormControl/context\";\nimport { hooks } from \"../../internal/stylingHooks\";\nimport styles from \"./autoComplete.module.scss\";\nimport { ESCAPE_CONSUMER_ATTRIBUTE } from \"@minerva/dom\";\nimport { resolveActiveOptionIndex } from \"@minerva/core\";\n\nconst DEFAULT_OFFSET = Object.freeze({ x: 0, y: 4 });\nconst EMPTY_OPTIONS: AutoCompleteOption[] = [];\n\nconst PLACEMENT = {\n top: \"top-start\",\n bottom: \"bottom-start\",\n left: \"left-start\",\n right: \"right-start\",\n} as const;\n\n/**\n * AutoComplete: a text input (combobox) that suggests options from a list.\n * Supports grouping, custom rendering and async loading; the input text can\n * be controlled or not. Focus stays in the input (`aria-activedescendant`).\n * For picking several values use `TagInput`.\n */\nconst AutoComplete = ({\n ref,\n name,\n label,\n mode = \"basic\",\n value,\n onChange,\n options = EMPTY_OPTIONS,\n defaultValue: defaultValueProp,\n onSelect,\n filterOption,\n groupBy,\n renderOption,\n renderEmpty,\n loading = false,\n inputProps,\n emptyProps,\n placement = \"bottom\",\n offset = DEFAULT_OFFSET,\n animation = true,\n sortOption,\n onOptionClick,\n onDropdownVisibleChange,\n dropdownClassName,\n onSubmit,\n autoHighlight = false,\n fillOnSelect = true,\n className,\n groupMode = \"first\",\n}: AutoCompleteProps) => {\n const [inputValue, setInputValue] = useControllableState({\n value,\n defaultValue: defaultValueProp ?? \"\",\n onChange,\n name: \"AutoComplete\",\n });\n const [visible, setVisible] = useControllableState({\n defaultValue: false,\n onChange: onDropdownVisibleChange,\n name: \"AutoComplete\",\n prop: \"open\",\n });\n // Keyboard highlight, by option identity (survives async option updates)\n const [focusedValue, setFocusedValue] = useState<string | number | null>(\n null,\n );\n const [hoveredIndex, setHoveredIndex] = useState(-1);\n const [container, setContainer] = useState<HTMLDivElement | null>(null);\n const [input, setInput] = useState<HTMLInputElement | null>(null);\n const setInputRef = useMergedRefs<HTMLInputElement>(setInput, ref);\n const [dropdown, setDropdown] = useState<HTMLDivElement | null>(null);\n const vertical = placement === \"top\" || placement === \"bottom\";\n\n const baseId = useId();\n const listboxId = `${baseId}-listbox`;\n // IME composition in progress: Enter / arrows belong to the IME.\n const composing = useRef(false);\n\n // FormControl wiring (id, disabled / read-only state, aria-*). The\n // input's own disabled / readOnly props still apply.\n const field = useFormControlProps({\n id: inputProps?.id,\n disabled: inputProps?.disabled,\n readOnly: inputProps?.readOnly,\n });\n const inputId = field.id ?? `${baseId}-input`;\n const blocked = !!field.disabled || !!field.readOnly;\n if (process.env.NODE_ENV !== \"production\") {\n warnControlledProps(\"AutoComplete\", {\n prop: \"value\",\n value,\n defaultProp: \"defaultValue\",\n defaultValue: defaultValueProp,\n handlerProp: \"onChange\",\n handler: onChange,\n locked: blocked,\n lockHint: \"set `inputProps.disabled` / `inputProps.readOnly`\",\n });\n }\n // A disabled / read-only field never shows (or keeps) the dropdown.\n const shown = visible && !blocked;\n\n const open = () => {\n if (!blocked) setVisible(true);\n };\n const close = () => {\n setVisible(false);\n setFocusedValue(null);\n };\n\n const processedOptions = useMemo(() => {\n const search = inputValue.toLowerCase();\n const result = options.filter((option) =>\n filterOption\n ? filterOption(inputValue, option)\n : option.label.toLowerCase().includes(search),\n );\n return sortOption ? [...result].sort(sortOption) : result;\n }, [options, inputValue, filterOption, sortOption]);\n\n /** Groups in order of first appearance, or runs of adjacent options */\n const groupedOptions = useMemo(() => {\n if (!groupBy) return null;\n if (groupMode === \"adjacent\") {\n const runs: [string, AutoCompleteOption[]][] = [];\n processedOptions.forEach((option) => {\n const group = groupBy(option);\n const last = runs[runs.length - 1];\n if (last && last[0] === group) last[1].push(option);\n else runs.push([group, [option]]);\n });\n return runs;\n }\n const groups = new Map<string, AutoCompleteOption[]>();\n processedOptions.forEach((option) => {\n const group = groupBy(option);\n const list = groups.get(group);\n if (list) list.push(option);\n else groups.set(group, [option]);\n });\n return Array.from(groups.entries());\n }, [processedOptions, groupBy, groupMode]);\n\n /** Options in display order; keyboard / hover indexes refer to this list */\n const navigableOptions = useMemo(\n () =>\n groupedOptions\n ? groupedOptions.flatMap(([, list]) => list)\n : processedOptions,\n [groupedOptions, processedOptions],\n );\n\n // Options the keyboard can reach: none while loading (they are hidden).\n const interactiveOptions = loading ? EMPTY_OPTIONS : navigableOptions;\n\n // With autoHighlight the first enabled option is active until the user\n // moves the highlight; a highlight whose option is gone falls back.\n const activeIndex = resolveActiveOptionIndex(\n interactiveOptions,\n focusedValue,\n autoHighlight && shown,\n );\n\n const moveFocus = (step: 1 | -1) => {\n const count = interactiveOptions.length;\n if (count === 0) return;\n // from \"nothing focused\", ArrowDown starts at the first option and\n // ArrowUp at the last one\n let index = activeIndex >= 0 ? activeIndex : step === 1 ? -1 : count;\n for (let i = 0; i < count; i += 1) {\n index = (index + step + count) % count;\n if (!interactiveOptions[index].disabled) {\n setFocusedValue(interactiveOptions[index].value);\n return;\n }\n }\n };\n\n const handleOptionSelect = (option: AutoCompleteOption) => {\n if (option.disabled) return;\n if (fillOnSelect) setInputValue(option.label);\n close();\n onSelect?.(option);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (\n blocked ||\n composing.current ||\n event.nativeEvent.isComposing ||\n event.keyCode === 229\n )\n return;\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!visible) open();\n moveFocus(1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!visible) open();\n moveFocus(-1);\n break;\n case \"Enter\": {\n const option = shown ? interactiveOptions[activeIndex] : undefined;\n if (option) {\n event.preventDefault();\n handleOptionSelect(option);\n } else if (onSubmit && inputValue.trim()) {\n // No active option: submit the typed text (e.g. a search).\n event.preventDefault();\n onSubmit(inputValue.trim());\n close();\n }\n break;\n }\n case \"Escape\":\n // Open: the dropdown's dismissable layer closes it (topmost only).\n // Closed: clears the text (APG combobox), `onChange(\"\")`.\n if (!shown && inputValue !== \"\") {\n event.preventDefault();\n setInputValue(\"\");\n setFocusedValue(null);\n }\n break;\n default:\n break;\n }\n };\n\n const handleInputChange = (next: string) => {\n setInputValue(next);\n setFocusedValue(null);\n open();\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n const next = event.relatedTarget as Node | null;\n if (next && (dropdown?.contains(next) || container?.contains(next))) return;\n close();\n };\n\n const handleOptionClick = (option: AutoCompleteOption) => {\n if (option.disabled || composing.current) return;\n handleOptionSelect(option);\n onOptionClick?.(option);\n input?.focus();\n };\n\n // Expose combobox semantics on the inner <input>\n const activeOptionId =\n shown && activeIndex >= 0\n ? `${listboxId}-option-${activeIndex}`\n : undefined;\n useEffect(() => {\n if (!input) return;\n input.setAttribute(\"role\", \"combobox\");\n input.setAttribute(\"aria-autocomplete\", \"list\");\n input.setAttribute(\"aria-expanded\", String(shown));\n // Closed with text: Escape clears it instead of closing an enclosing\n // Modal / Drawer / Popover\n if (!shown && inputValue !== \"\") {\n input.setAttribute(ESCAPE_CONSUMER_ATTRIBUTE, \"\");\n } else input.removeAttribute(ESCAPE_CONSUMER_ATTRIBUTE);\n if (shown) input.setAttribute(\"aria-controls\", listboxId);\n else input.removeAttribute(\"aria-controls\");\n if (activeOptionId)\n input.setAttribute(\"aria-activedescendant\", activeOptionId);\n else input.removeAttribute(\"aria-activedescendant\");\n }, [input, shown, listboxId, activeOptionId, inputValue]);\n\n // Clicking the still-focused input (after a pick or Escape) reopens the\n // dropdown; focus alone does not fire again.\n const reopenRef = useRef(() => {});\n useEffect(() => {\n reopenRef.current = () => {\n if (!visible) open();\n };\n });\n useEffect(() => {\n if (!input) return;\n const onClick = () => reopenRef.current();\n input.addEventListener(\"click\", onClick);\n return () => input.removeEventListener(\"click\", onClick);\n }, [input]);\n\n // Keep the keyboard-focused option scrolled into view\n useEffect(() => {\n if (!activeOptionId) return;\n document\n .getElementById(activeOptionId)\n ?.scrollIntoView?.({ block: \"nearest\" });\n }, [activeOptionId]);\n\n const renderBasicOption = (option: AutoCompleteOption) => (\n <div className={styles.basicOption}>\n {option.icon && <span className={styles.icon}>{option.icon}</span>}\n <div className={styles.content}>\n <div className={styles.label}>{option.label}</div>\n {option.description && (\n <div className={styles.description}>{option.description}</div>\n )}\n </div>\n </div>\n );\n\n const renderOptionItem = (option: AutoCompleteOption, index: number) => {\n const active = activeIndex === index;\n const highlighted = hoveredIndex === index || active;\n return (\n <div\n key={option.value}\n className={cn(styles.optionItem, {\n [styles.disabled]: option.disabled,\n [styles.highlight]: option.highlight,\n [styles.active]: highlighted,\n })}\n style={option.style}\n role=\"option\"\n // Focus stays in the input (aria-activedescendant); -1 keeps the\n // option out of the tab order while making it programmatically\n // focusable.\n tabIndex={-1}\n id={`${listboxId}-option-${index}`}\n aria-selected={active}\n aria-disabled={option.disabled || undefined}\n // keep focus (and the open dropdown) in the input while clicking\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleOptionClick(option)}\n onKeyDown={(e) => {\n if (e.key !== \"Enter\" && e.key !== \" \") return;\n e.preventDefault();\n handleOptionClick(option);\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(-1)}\n {...hooks(\"autocomplete\", \"item\", {\n highlighted,\n disabled: option.disabled,\n })}\n >\n {mode === \"custom\" && renderOption\n ? renderOption(option)\n : renderBasicOption(option)}\n </div>\n );\n };\n\n return (\n <div\n ref={setContainer}\n className={cn(styles.autoComplete, className)}\n onCompositionStart={() => {\n composing.current = true;\n }}\n onCompositionEnd={() => {\n composing.current = false;\n }}\n {...hooks(\"autocomplete\", \"root\", {\n state: shown ? \"open\" : \"closed\",\n disabled: !!field.disabled,\n readonly: !!field.readOnly,\n loading,\n })}\n >\n {label && (\n <label\n htmlFor={inputId}\n className={styles.label}\n {...hooks(\"autocomplete\", \"label\")}\n >\n {label}\n </label>\n )}\n <Input\n {...inputProps}\n id={inputId}\n disabled={field.disabled}\n readOnly={field.readOnly}\n name={name}\n ref={setInputRef}\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n onFocus={(e) => {\n open();\n inputProps?.onFocus?.(e);\n }}\n onBlur={(e) => {\n handleBlur(e);\n inputProps?.onBlur?.(e);\n }}\n onKeyDown={(e) => {\n handleKeyDown(e);\n inputProps?.onKeyDown?.(e);\n }}\n />\n\n <FloatingPanel\n ref={setDropdown}\n open={shown}\n anchor={container}\n placement={PLACEMENT[placement]}\n offset={{\n mainAxis: vertical ? offset.y : offset.x,\n crossAxis: vertical ? offset.x : offset.y,\n }}\n matchAnchorWidth=\"min\"\n // the field (label, input, suffix) is part of the dropdown layer\n branches={() => [container]}\n onEscapeKeyDown={(event) => {\n // Escape during IME composition cancels the composition only\n if (composing.current || event.isComposing) event.preventDefault();\n }}\n onDismiss={close}\n returnFocusOnEscape={() => input}\n className={cn(styles.popup, dropdownClassName)}\n {...hooks(\"autocomplete\", \"content\", { state: \"open\" })}\n >\n <div className={cn(styles.dropdown, animation && styles.animated)}>\n {/* While open the listbox always exists (aria-controls target);\n loading / empty states are presentational rows inside it. */}\n <div\n className={styles.optionList}\n role=\"listbox\"\n id={listboxId}\n aria-label={label}\n aria-busy={loading || undefined}\n {...hooks(\"autocomplete\", \"list\")}\n >\n {loading ? (\n <div\n role=\"presentation\"\n className={styles.loading}\n {...hooks(\"autocomplete\", \"loading\")}\n >\n <ProgressIndicator />\n </div>\n ) : processedOptions.length > 0 ? (\n <>\n {groupedOptions\n ? groupedOptions.map(([group, groupOptions], groupIndex) =>\n group === \"\" ? (\n // ungrouped options: no heading\n <React.Fragment key={`${groupIndex}-`}>\n {groupOptions.map((option) =>\n renderOptionItem(\n option,\n navigableOptions.indexOf(option),\n ),\n )}\n </React.Fragment>\n ) : (\n <div\n key={`${groupIndex}-${group}`}\n className={styles.optionGroup}\n role=\"group\"\n aria-label={group}\n >\n <div\n className={styles.groupLabel}\n aria-hidden=\"true\"\n {...hooks(\"autocomplete\", \"group-label\")}\n >\n {group}\n </div>\n {groupOptions.map((option) =>\n renderOptionItem(\n option,\n navigableOptions.indexOf(option),\n ),\n )}\n </div>\n ),\n )\n : processedOptions.map((option, index) =>\n renderOptionItem(option, index),\n )}\n </>\n ) : (\n <div\n role=\"presentation\"\n className={styles.empty}\n {...hooks(\"autocomplete\", \"empty\")}\n >\n {renderEmpty?.() || <Empty {...emptyProps} />}\n </div>\n )}\n </div>\n </div>\n </FloatingPanel>\n </div>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs");require("../../utils/cn.cjs");const t=require("../../hooks/useI18n.cjs"),n=require("../../internal/stylingHooks.cjs"),r=require("../../internal/devWarnings.cjs"),i=require("../../internal/icons.cjs"),a=require("../../internal/mergeRefs.cjs"),ee=require("../../internal/dataAttributes.cjs"),o=require("../../internal/useControllableState.cjs"),s=require("../FormControl/context.cjs"),te=require("../../internal/useDismissableLayer.cjs");require("../../internal/direction.cjs");const ne=require("../../internal/FloatingPanel.cjs"),re=require("../IconButton/IconButton.cjs");require("../IconButton/index.cjs");const ie=require("../Input/Input.cjs");require("../Input/index.cjs");const c=require("../../internal/tabbing.cjs"),l=require("./datePicker.module.scss.cjs");let u=require("react");u=e.__toESM(u,1);let d=require("../../../core/index.cjs"),f=require("react/jsx-runtime"),ae=require("../../../dom/index.cjs");var oe=[`mon`,`tue`,`wed`,`thu`,`fri`,`sat`,`sun`],p=({ref:e,value:p,defaultValue:m,onChange:h,placeholder:se,label:g,"aria-label":_,"aria-labelledby":ce,"aria-describedby":le,id:ue,required:de,readOnly:fe,invalid:pe,name:me=`date-picker`,disabled:he,clearable:v=!0,size:y=`medium`,minDate:b,maxDate:x,locale:ge,className:_e=``,style:ve,onOpenChange:ye,...be})=>{let{t:S,language:xe}=t.default(),C=(0,u.useId)(),w=s.useFormControlContext(),T=s.useFormControlProps({id:ue,"aria-describedby":le}),E=he??w?.disabled??!1,D=fe??w?.readOnly??!1,Se=de??w?.required??!1,O=pe??w?.invalid??!1,k=g??_??S(`datePicker.label`),A=ce??(w&&!g&&!_?w.labelId:void 0);process.env.NODE_ENV!==`production`&&r.warnControlledProps(`DatePicker`,{prop:`value`,value:p===null?``:p,defaultProp:`defaultValue`,defaultValue:m,handlerProp:`onChange`,handler:h,locked:E||D,lockHint:"set `disabled` / `readOnly`"});let[j,Ce]=o.useControllableState({value:p===null?``:p,defaultValue:m??``,name:`DatePicker`}),[M,N]=o.useControllableState({defaultValue:!1,onChange:ye,name:`DatePicker`,prop:`open`}),[P,F]=(0,u.useState)(null),[I,we]=(0,u.useState)(null),[Te,Ee]=(0,u.useState)(null),De=a.useMergedRefs(we,e),L=(0,u.useRef)(null),Oe=te.useLayerParent(),ke=(0,d.parseDayKey)(j||``)??new Date,[R,z]=(0,u.useState)(()=>(0,d.monthStart)(ke)),[B,V]=(0,u.useState)(``),[Ae,H]=(0,u.useState)(!1),U=(0,u.useRef)(new Map),W=(0,u.useRef)(null),G=e=>!!(b&&e<b||x&&e>x),K=e=>{Ce(e),h?.(e)},q=e=>{let t=(0,d.parseDayKey)(e);t&&z((0,d.monthStart)(t))},je=e=>{if(F(e),e===``){K(``);return}let t=(0,d.parseDayKey)(e,!0);if(t){let e=(0,d.dayKey)(t);G(e)||(K(e),z((0,d.monthStart)(t)))}},Me=()=>{if(P===null)return;let e=P.trim();if(e===``)j&&K(``);else{let t=(0,d.parseDayKey)(e,!1);if(t){let e=(0,d.dayKey)(t);!G(e)&&e!==j&&(K(e),z((0,d.monthStart)(t)))}}F(null)},J=()=>{F(null),K(``),I?.focus()},Y=e=>{let t=(0,d.dayKey)(e);E||D||G(t)||(F(null),K(t),z((0,d.monthStart)(e)),N(!1),I?.focus())},Ne=()=>{E||D||(H(!1),M||q(j),N(e=>!e))},X=(0,d.monthStart)(R),Pe=(0,d.addDays)(X,-((X.getDay()+6)%7)),Fe=Array.from({length:42},(e,t)=>(0,d.addDays)(Pe,t)),Ie=Fe.map(d.dayKey),Z=new Date,Q=(0,d.dayKey)(Z),$=[B,j,(0,d.sameMonth)(Z,R)?Q:``,(0,d.dayKey)(X)].find(e=>e&&Ie.includes(e)),Le=(0,d.dayKey)(X);(0,u.useEffect)(()=>{if(!M||E||!W.current)return;let e=U.current.get(W.current);e&&(W.current=null,e.focus())},[M,Le,B,E]);let Re=(e,t)=>{if(E||D)return;if(e.key===`Enter`||e.key===` `){e.preventDefault(),e.repeat||Y(t);return}let n,r=(t.getDay()+6)%7;switch((0,ae.logicalArrowKey)(e.key,e.currentTarget)){case`ArrowLeft`:n=(0,d.addDays)(t,-1);break;case`ArrowRight`:n=(0,d.addDays)(t,1);break;case`ArrowUp`:n=(0,d.addDays)(t,-7);break;case`ArrowDown`:n=(0,d.addDays)(t,7);break;case`Home`:n=(0,d.addDays)(t,-r);break;case`End`:n=(0,d.addDays)(t,6-r);break;case`PageUp`:case`PageDown`:{let r=(e.key===`PageUp`?-1:1)*(e.shiftKey?12:1),i=(0,d.monthStart)(t,r),a=(0,d.addDays)((0,d.monthStart)(i,1),-1).getDate();n=(0,d.localDate)(i.getFullYear(),i.getMonth(),Math.min(t.getDate(),a));break}default:return}e.preventDefault();let i=(0,d.dayKey)(n);W.current=i,V(i),(0,d.sameMonth)(n,R)||z((0,d.monthStart)(n))},ze=e=>{let t=e.currentTarget;!I||e.key!==`Tab`||e.altKey||e.ctrlKey||e.metaKey||!c.tabLeavesPanel(t,e.target,e.shiftKey)||(e.preventDefault(),(e.shiftKey?I:c.adjacentTabbable(I,Oe??I.ownerDocument.body,!1)??I).focus(),N(!1))},Be=new Intl.DateTimeFormat(ge??xe,{year:`numeric`,month:`long`}).format(X),Ve=P??j;return(0,f.jsxs)(`div`,{...ee.pickDataAttributes(be),...n.hooks(`date-picker`,`root`,{state:M&&!E&&!D?`open`:`closed`,disabled:E,readonly:D,invalid:O,size:y}),ref:Ee,className:(0,d.cn)(l.default.datePicker,_e),style:ve,onClick:e=>{e.target===I&&Ne()},children:[(0,f.jsx)(s.FormControlContext.Provider,{value:null,children:(0,f.jsx)(ie.Input,{ref:De,value:Ve,placeholder:se??S(`datePicker.placeholder`),id:T.id,"aria-label":k,"aria-labelledby":A,"aria-describedby":T[`aria-describedby`],"aria-invalid":O||void 0,"aria-readonly":D||void 0,required:Se,readOnly:D,onChange:e=>je(e.target.value),onBlur:Me,onKeyDown:e=>{e.key===`ArrowDown`&&(e.preventDefault(),M?L.current?.querySelector(`[role="gridcell"][tabindex="0"]`)?.focus():(q(j),V(j||Q),H(!0),N(!0)))},name:me,disabled:E,size:y,suffix:v&&j&&!E&&!D?(0,f.jsx)(re.default,{icon:(0,f.jsx)(i.IconX,{"aria-hidden":!0,focusable:!1}),size:`small`,"aria-label":S(`datePicker.clear`),onClick:J,className:l.default.clearButton}):(0,f.jsx)(`span`,{className:l.default.calendarIcon,"aria-hidden":`true`,...n.hooks(`date-picker`,`icon`),children:(0,f.jsx)(i.IconCalendar,{})})})}),(0,f.jsx)(ne.FloatingPanel,{ref:L,open:M&&!E&&!D,anchor:I,placement:`bottom-start`,branches:()=>[Te],onDismiss:()=>N(!1),returnFocusOnEscape:()=>I,focusable:!0,role:`dialog`,tabIndex:-1,"aria-label":k,"aria-labelledby":A,className:l.default.popup,onKeyDown:ze,...n.hooks(`date-picker`,`content`,{state:`open`}),children:(0,f.jsxs)(`div`,{className:l.default.panel,children:[(0,f.jsxs)(`div`,{className:l.default.header,children:[(0,f.jsx)(`h2`,{id:C,className:l.default.heading,"aria-live":`polite`,children:Be}),(0,f.jsxs)(`div`,{className:l.default.navGroup,children:[(0,f.jsx)(`button`,{type:`button`,className:l.default.navButton,"aria-label":S(`monthCalendar.previousMonth`),onClick:()=>z((0,d.monthStart)(R,-1)),children:(0,f.jsx)(i.IconChevronLeft,{"aria-hidden":!0,focusable:!1})}),(0,f.jsx)(`button`,{type:`button`,className:l.default.navButton,"aria-label":S(`monthCalendar.nextMonth`),onClick:()=>z((0,d.monthStart)(R,1)),children:(0,f.jsx)(i.IconChevronRight,{"aria-hidden":!0,focusable:!1})})]})]}),(0,f.jsxs)(`div`,{role:`grid`,"aria-labelledby":C,className:l.default.grid,children:[(0,f.jsx)(`div`,{role:`row`,className:l.default.week,children:oe.map(e=>(0,f.jsx)(`div`,{role:`columnheader`,className:l.default.weekday,children:S(`monthCalendar.weekdays.${e}`)},e))}),Array.from({length:6},(e,t)=>(0,f.jsx)(`div`,{role:`row`,className:l.default.week,children:Fe.slice(t*7,t*7+7).map(e=>{let t=(0,d.dayKey)(e),n=j===t,r=!(0,d.sameMonth)(e,R),i=t===Q,a=G(t);return(0,f.jsx)(`div`,{role:`gridcell`,className:l.default.day,ref:e=>{e?(U.current.set(t,e),(Ae&&t===$||W.current===t)&&(W.current=null,e.focus())):U.current.delete(t)},"data-date":t,"data-outside":r?``:void 0,"aria-label":t,"aria-selected":n,"aria-current":i?`date`:void 0,"aria-disabled":a||void 0,tabIndex:!a&&t===$?0:-1,onFocus:()=>V(t),onClick:()=>Y(e),onKeyDown:t=>Re(t,e),children:e.getDate()},t)})},t))]}),(0,f.jsxs)(`div`,{className:l.default.footer,children:[(0,f.jsx)(`button`,{type:`button`,className:l.default.footerButton,disabled:G(Q),onClick:()=>Y(Z),children:S(`datePicker.today`)}),v&&j&&(0,f.jsx)(`button`,{type:`button`,className:l.default.footerButton,onClick:()=>{J(),N(!1)},children:S(`datePicker.clear`)})]})]})})]})},m=u.default.memo(p);exports.DatePicker=p,exports.default=m;
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs");require("../../utils/cn.cjs");const t=require("../../hooks/useI18n.cjs"),n=require("../../internal/stylingHooks.cjs"),r=require("../../internal/devWarnings.cjs"),i=require("../../internal/icons.cjs"),a=require("../../internal/mergeRefs.cjs"),ee=require("../../internal/dataAttributes.cjs"),o=require("../../internal/useControllableState.cjs"),s=require("../FormControl/context.cjs"),te=require("../../internal/useDismissableLayer.cjs");require("../../internal/direction.cjs");const ne=require("../../internal/FloatingPanel.cjs"),re=require("../IconButton/IconButton.cjs");require("../IconButton/index.cjs");const ie=require("../Input/Input.cjs");require("../Input/index.cjs");const c=require("../../internal/tabbing.cjs"),l=require("./datePicker.module.scss.cjs");let u=require("react");u=e.__toESM(u,1);let d=require("../../../core/index.cjs"),f=require("react/jsx-runtime"),ae=require("../../../dom/index.cjs");var oe=[`mon`,`tue`,`wed`,`thu`,`fri`,`sat`,`sun`],p=({ref:e,value:p,defaultValue:m,onChange:h,placeholder:se,label:g,"aria-label":_,"aria-labelledby":ce,"aria-describedby":le,id:ue,required:de,readOnly:fe,invalid:pe,name:me=`date-picker`,disabled:he,clearable:v=!0,size:y=`medium`,minDate:b,maxDate:x,locale:ge,className:_e=``,style:ve,onOpenChange:ye,...be})=>{let{t:S,language:xe}=t.default(),C=(0,u.useId)(),w=s.useFormControlContext(),T=s.useFormControlProps({id:ue,"aria-describedby":le}),E=he??w?.disabled??!1,D=fe??w?.readOnly??!1,Se=de??w?.required??!1,O=pe??w?.invalid??!1,k=g??_??S(`datePicker.label`),A=ce??(w&&!g&&!_?w.labelId:void 0);process.env.NODE_ENV!==`production`&&r.warnControlledProps(`DatePicker`,{prop:`value`,value:p===null?``:p,defaultProp:`defaultValue`,defaultValue:m,handlerProp:`onChange`,handler:h,locked:E||D,lockHint:"set `disabled` / `readOnly`"});let[j,Ce]=o.useControllableState({value:p===null?``:p,defaultValue:m??``,name:`DatePicker`}),[M,N]=o.useControllableState({defaultValue:!1,onChange:ye,name:`DatePicker`,prop:`open`}),[P,F]=(0,u.useState)(null),[I,we]=(0,u.useState)(null),[Te,Ee]=(0,u.useState)(null),De=a.useMergedRefs(we,e),L=(0,u.useRef)(null),Oe=te.useLayerParent(),ke=(0,d.parseDayKey)(j||``)??new Date,[R,z]=(0,u.useState)(()=>(0,d.monthStart)(ke)),[B,V]=(0,u.useState)(``),[Ae,H]=(0,u.useState)(!1),U=(0,u.useRef)(new Map),W=(0,u.useRef)(null),G=e=>!!(b&&e<b||x&&e>x),K=e=>{Ce(e),h?.(e)},q=e=>{let t=(0,d.parseDayKey)(e);t&&z((0,d.monthStart)(t))},je=e=>{if(F(e),e===``){K(``);return}let t=(0,d.parseDayKey)(e,!0);if(t){let e=(0,d.dayKey)(t);G(e)||(K(e),z((0,d.monthStart)(t)))}},Me=()=>{if(P===null)return;let e=P.trim();if(e===``)j&&K(``);else{let t=(0,d.parseDayKey)(e,!1);if(t){let e=(0,d.dayKey)(t);!G(e)&&e!==j&&(K(e),z((0,d.monthStart)(t)))}}F(null)},J=()=>{F(null),K(``),I?.focus()},Y=e=>{let t=(0,d.dayKey)(e);E||D||G(t)||(F(null),K(t),z((0,d.monthStart)(e)),N(!1),I?.focus())},Ne=()=>{E||D||(H(!1),M||q(j),N(e=>!e))},X=(0,d.monthStart)(R),Pe=(0,d.addDays)(X,-((X.getDay()+6)%7)),Fe=Array.from({length:42},(e,t)=>(0,d.addDays)(Pe,t)),Ie=Fe.map(d.dayKey),Z=new Date,Q=(0,d.dayKey)(Z),$=[B,j,(0,d.sameMonth)(Z,R)?Q:``,(0,d.dayKey)(X),...Ie].find(e=>e&&Ie.includes(e)&&!G(e)),Le=(0,d.dayKey)(X);(0,u.useEffect)(()=>{if(!M||E||!W.current)return;let e=U.current.get(W.current);e&&(W.current=null,e.focus())},[M,Le,B,E]);let Re=(e,t)=>{if(E||D)return;if(e.key===`Enter`||e.key===` `){e.preventDefault(),e.repeat||Y(t);return}let n,r=(t.getDay()+6)%7;switch((0,ae.logicalArrowKey)(e.key,e.currentTarget)){case`ArrowLeft`:n=(0,d.addDays)(t,-1);break;case`ArrowRight`:n=(0,d.addDays)(t,1);break;case`ArrowUp`:n=(0,d.addDays)(t,-7);break;case`ArrowDown`:n=(0,d.addDays)(t,7);break;case`Home`:n=(0,d.addDays)(t,-r);break;case`End`:n=(0,d.addDays)(t,6-r);break;case`PageUp`:case`PageDown`:{let r=(e.key===`PageUp`?-1:1)*(e.shiftKey?12:1),i=(0,d.monthStart)(t,r),a=(0,d.addDays)((0,d.monthStart)(i,1),-1).getDate();n=(0,d.localDate)(i.getFullYear(),i.getMonth(),Math.min(t.getDate(),a));break}default:return}e.preventDefault();let i=(0,d.dayKey)(n);W.current=i,V(i),(0,d.sameMonth)(n,R)||z((0,d.monthStart)(n))},ze=e=>{let t=e.currentTarget;!I||e.key!==`Tab`||e.altKey||e.ctrlKey||e.metaKey||!c.tabLeavesPanel(t,e.target,e.shiftKey)||(e.preventDefault(),(e.shiftKey?I:c.adjacentTabbable(I,Oe??I.ownerDocument.body,!1)??I).focus(),N(!1))},Be=new Intl.DateTimeFormat(ge??xe,{year:`numeric`,month:`long`}).format(X),Ve=P??j;return(0,f.jsxs)(`div`,{...ee.pickDataAttributes(be),...n.hooks(`date-picker`,`root`,{state:M&&!E&&!D?`open`:`closed`,disabled:E,readonly:D,invalid:O,size:y}),ref:Ee,className:(0,d.cn)(l.default.datePicker,_e),style:ve,onClick:e=>{e.target===I&&Ne()},children:[(0,f.jsx)(s.FormControlContext.Provider,{value:null,children:(0,f.jsx)(ie.Input,{ref:De,value:Ve,placeholder:se??S(`datePicker.placeholder`),id:T.id,"aria-label":k,"aria-labelledby":A,"aria-describedby":T[`aria-describedby`],"aria-invalid":O||void 0,"aria-readonly":D||void 0,required:Se,readOnly:D,onChange:e=>je(e.target.value),onBlur:Me,onKeyDown:e=>{e.key===`ArrowDown`&&(e.preventDefault(),M?L.current?.querySelector(`[role="gridcell"][tabindex="0"]`)?.focus():(q(j),V(j||Q),H(!0),N(!0)))},name:me,disabled:E,size:y,suffix:v&&j&&!E&&!D?(0,f.jsx)(re.default,{icon:(0,f.jsx)(i.IconX,{"aria-hidden":!0,focusable:!1}),size:`small`,"aria-label":S(`datePicker.clear`),onClick:J,className:l.default.clearButton}):(0,f.jsx)(`span`,{className:l.default.calendarIcon,"aria-hidden":`true`,...n.hooks(`date-picker`,`icon`),children:(0,f.jsx)(i.IconCalendar,{})})})}),(0,f.jsx)(ne.FloatingPanel,{ref:L,open:M&&!E&&!D,anchor:I,placement:`bottom-start`,branches:()=>[Te],onDismiss:()=>N(!1),returnFocusOnEscape:()=>I,focusable:!0,role:`dialog`,tabIndex:-1,"aria-label":k,"aria-labelledby":A,className:l.default.popup,onKeyDown:ze,...n.hooks(`date-picker`,`content`,{state:`open`}),children:(0,f.jsxs)(`div`,{className:l.default.panel,children:[(0,f.jsxs)(`div`,{className:l.default.header,children:[(0,f.jsx)(`h2`,{id:C,className:l.default.heading,"aria-live":`polite`,children:Be}),(0,f.jsxs)(`div`,{className:l.default.navGroup,children:[(0,f.jsx)(`button`,{type:`button`,className:l.default.navButton,"aria-label":S(`monthCalendar.previousMonth`),onClick:()=>z((0,d.monthStart)(R,-1)),children:(0,f.jsx)(i.IconChevronLeft,{"aria-hidden":!0,focusable:!1})}),(0,f.jsx)(`button`,{type:`button`,className:l.default.navButton,"aria-label":S(`monthCalendar.nextMonth`),onClick:()=>z((0,d.monthStart)(R,1)),children:(0,f.jsx)(i.IconChevronRight,{"aria-hidden":!0,focusable:!1})})]})]}),(0,f.jsxs)(`div`,{role:`grid`,"aria-labelledby":C,className:l.default.grid,children:[(0,f.jsx)(`div`,{role:`row`,className:l.default.week,children:oe.map(e=>(0,f.jsx)(`div`,{role:`columnheader`,className:l.default.weekday,children:S(`monthCalendar.weekdays.${e}`)},e))}),Array.from({length:6},(e,t)=>(0,f.jsx)(`div`,{role:`row`,className:l.default.week,children:Fe.slice(t*7,t*7+7).map(e=>{let t=(0,d.dayKey)(e),n=j===t,r=!(0,d.sameMonth)(e,R),i=t===Q,a=G(t);return(0,f.jsx)(`div`,{role:`gridcell`,className:l.default.day,ref:e=>{e?(U.current.set(t,e),(Ae&&t===$||W.current===t)&&(W.current=null,e.focus())):U.current.delete(t)},"data-date":t,"data-outside":r?``:void 0,"aria-label":t,"aria-selected":n,"aria-current":i?`date`:void 0,"aria-disabled":a||void 0,tabIndex:!a&&t===$?0:-1,onFocus:()=>V(t),onClick:()=>Y(e),onKeyDown:t=>Re(t,e),children:e.getDate()},t)})},t))]}),(0,f.jsxs)(`div`,{className:l.default.footer,children:[(0,f.jsx)(`button`,{type:`button`,className:l.default.footerButton,disabled:G(Q),onClick:()=>Y(Z),children:S(`datePicker.today`)}),v&&j&&(0,f.jsx)(`button`,{type:`button`,className:l.default.footerButton,onClick:()=>{J(),N(!1)},children:S(`datePicker.clear`)})]})]})})]})},m=u.default.memo(p);exports.DatePicker=p,exports.default=m;
|
|
2
2
|
//# sourceMappingURL=DatePicker.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.cjs","names":["useI18n","useId","useFormControlContext","useFormControlProps","useControllableState","useState","useMergedRefs","useRef","useLayerParent","parseDayKey","monthStart","dayKey","addDays","sameMonth","logicalArrowKey","localDate","tabLeavesPanel","adjacentTabbable","pickDataAttributes","hooks","cn","styles","FormControlContext","Input","IconButton","IconX","IconCalendar","FloatingPanel","IconChevronLeft","IconChevronRight","React","require_runtime","require_useI18n","require_stylingHooks","require_devWarnings","require_icons","require_mergeRefs","require_dataAttributes","require_useControllableState","require_context","require_useDismissableLayer","require_FloatingPanel","require_IconButton","require_Input","require_tabbing","require_datePicker_module","react","_minerva_core","react_jsx_runtime","_minerva_dom","WEEKDAYS","DatePicker","ariaLabel","ariaLabelledBy","ariaDescribedBy","requiredProp","readOnlyProp","invalidProp","disabledProp","rest","headingId","fc","fieldProps","disabled","readOnly","required","invalid","accessibleName","label","t","labelledBy","value","onChange","current","setCurrent","defaultValue","open","setOpen","onOpenChange","draft","setDraft","input","setInput","field","setField","setInputRef","ref","panelRef","tabContainer","initialDate","month","setMonth","focusedKey","setFocusedKey","focusPanelOnOpen","setFocusPanelOnOpen","cells","pendingFocus","isDayDisabled","minDate","key","maxDate","commit","next","syncMonthFromValue","parsed","val","handleInputChange","text","handleInputBlur","trimmed","handleClear","selectDate","date","toggle","prev","first","start","days","index","visibleKeys","today","todayKey","activeKey","monthKey","cell","handleDayKeyDown","event","target","weekday","offset","lastDay","nextKey","handlePanelKeyDown","panel","heading","locale","language","displayValue","className","placeholder","clearable","day","week","selected","outside","isToday","dayDisabled","element","DatePicker_default"],"sources":["../../../../../react/src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from \"react\";\nimport {\n addDays,\n dayKey,\n localDate,\n monthStart,\n parseDayKey,\n sameMonth,\n} from \"@minerva/core\";\nimport { cn } from \"../../utils/cn\";\nimport {\n IconCalendar,\n IconChevronLeft,\n IconChevronRight,\n IconX,\n} from \"../../internal/icons\";\nimport { Input } from \"../Input\";\nimport { IconButton } from \"../IconButton\";\nimport { FloatingPanel } from \"../../internal/FloatingPanel\";\nimport { useLayerParent } from \"../../internal/useDismissableLayer\";\nimport { adjacentTabbable, tabLeavesPanel } from \"../../internal/tabbing\";\nimport { useControllableState } from \"../../internal/useControllableState\";\nimport { warnControlledProps } from \"../../internal/devWarnings\";\nimport { useMergedRefs } from \"../../internal/mergeRefs\";\nimport useI18n from \"../../hooks/useI18n\";\nimport { pickDataAttributes } from \"../../internal/dataAttributes\";\nimport { logicalArrowKey } from \"../../internal/direction\";\nimport {\n FormControlContext,\n useFormControlContext,\n useFormControlProps,\n} from \"../FormControl/context\";\nimport type { DatePickerProps } from \"./types\";\nimport { hooks } from \"../../internal/stylingHooks\";\nimport styles from \"./datePicker.module.scss\";\n\nconst WEEKDAYS = [\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"] as const;\n\n/**\n * DatePicker: type a `\"YYYY-MM-DD\"` date or pick a day from a popup month\n * calendar grid. Works controlled (`value` + `onChange`) or uncontrolled\n * (`defaultValue`). Inside a FormControl the input picks up the field's id,\n * label, description, invalid, required, disabled and read-only state\n * (explicit props win).\n */\nconst DatePicker = ({\n ref,\n value,\n defaultValue,\n onChange,\n placeholder,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n id,\n required: requiredProp,\n readOnly: readOnlyProp,\n invalid: invalidProp,\n name = \"date-picker\",\n disabled: disabledProp,\n clearable = true,\n size = \"medium\",\n minDate,\n maxDate,\n locale,\n className = \"\",\n style,\n onOpenChange,\n ...rest\n}: DatePickerProps) => {\n const { t, language } = useI18n();\n const headingId = useId();\n const fc = useFormControlContext();\n const fieldProps = useFormControlProps({\n id,\n \"aria-describedby\": ariaDescribedBy,\n });\n const disabled = disabledProp ?? fc?.disabled ?? false;\n const readOnly = readOnlyProp ?? fc?.readOnly ?? false;\n const required = requiredProp ?? fc?.required ?? false;\n const invalid = invalidProp ?? fc?.invalid ?? false;\n const accessibleName = label ?? ariaLabel ?? t(\"datePicker.label\");\n const labelledBy =\n ariaLabelledBy ?? (fc && !label && !ariaLabel ? fc.labelId : undefined);\n\n if (process.env.NODE_ENV !== \"production\") {\n warnControlledProps(\"DatePicker\", {\n prop: \"value\",\n value: value === null ? \"\" : value,\n defaultProp: \"defaultValue\",\n defaultValue,\n handlerProp: \"onChange\",\n handler: onChange,\n locked: disabled || readOnly,\n lockHint: \"set `disabled` / `readOnly`\",\n });\n }\n\n const normalizedValue = value === null ? \"\" : value;\n const [current, setCurrent] = useControllableState<string>({\n value: normalizedValue,\n defaultValue: defaultValue ?? \"\",\n name: \"DatePicker\",\n });\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: onOpenChange,\n name: \"DatePicker\",\n prop: \"open\",\n });\n\n const [draft, setDraft] = useState<string | null>(null);\n const [input, setInput] = useState<HTMLInputElement | null>(null);\n const [field, setField] = useState<HTMLDivElement | null>(null);\n const setInputRef = useMergedRefs<HTMLInputElement>(setInput, ref);\n const panelRef = useRef<HTMLDivElement>(null);\n const tabContainer = useLayerParent();\n\n const initialDate = parseDayKey(current || \"\") ?? new Date();\n const [month, setMonth] = useState<Date>(() => monthStart(initialDate));\n const [focusedKey, setFocusedKey] = useState(\"\");\n const [focusPanelOnOpen, setFocusPanelOnOpen] = useState(false);\n const cells = useRef(new Map<string, HTMLDivElement>());\n const pendingFocus = useRef<string | null>(null);\n\n const isDayDisabled = (key: string) => {\n if (minDate && key < minDate) return true;\n if (maxDate && key > maxDate) return true;\n return false;\n };\n\n const commit = (next: string) => {\n setCurrent(next);\n onChange?.(next);\n };\n\n const syncMonthFromValue = (val: string) => {\n const parsed = parseDayKey(val);\n if (parsed) setMonth(monthStart(parsed));\n };\n\n const handleInputChange = (text: string) => {\n setDraft(text);\n if (text === \"\") {\n commit(\"\");\n return;\n }\n const parsed = parseDayKey(text, true);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key)) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n };\n\n const handleInputBlur = () => {\n if (draft === null) return;\n const trimmed = draft.trim();\n if (trimmed === \"\") {\n if (current) commit(\"\");\n } else {\n const parsed = parseDayKey(trimmed, false);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key) && key !== current) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n }\n setDraft(null);\n };\n\n const handleClear = () => {\n setDraft(null);\n commit(\"\");\n input?.focus();\n };\n\n const selectDate = (date: Date) => {\n const key = dayKey(date);\n if (disabled || readOnly || isDayDisabled(key)) return;\n setDraft(null);\n commit(key);\n setMonth(monthStart(date));\n setOpen(false);\n input?.focus();\n };\n\n const toggle = () => {\n if (disabled || readOnly) return;\n setFocusPanelOnOpen(false);\n if (!open) syncMonthFromValue(current);\n setOpen((prev) => !prev);\n };\n\n const first = monthStart(month);\n const start = addDays(first, -((first.getDay() + 6) % 7));\n const days = Array.from({ length: 42 }, (_, index) => addDays(start, index));\n const visibleKeys = days.map(dayKey);\n const today = new Date();\n const todayKey = dayKey(today);\n const activeKey = [\n focusedKey,\n current,\n sameMonth(today, month) ? todayKey : \"\",\n dayKey(first),\n ].find((key) => key && visibleKeys.includes(key));\n const monthKey = dayKey(first);\n\n useEffect(() => {\n if (!open || disabled || !pendingFocus.current) return;\n const cell = cells.current.get(pendingFocus.current);\n if (cell) {\n pendingFocus.current = null;\n cell.focus();\n }\n }, [open, monthKey, focusedKey, disabled]);\n\n const handleDayKeyDown = (\n event: React.KeyboardEvent<HTMLDivElement>,\n date: Date,\n ) => {\n if (disabled || readOnly) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (!event.repeat) selectDate(date);\n return;\n }\n let target: Date;\n const weekday = (date.getDay() + 6) % 7;\n switch (logicalArrowKey(event.key, event.currentTarget)) {\n case \"ArrowLeft\":\n target = addDays(date, -1);\n break;\n case \"ArrowRight\":\n target = addDays(date, 1);\n break;\n case \"ArrowUp\":\n target = addDays(date, -7);\n break;\n case \"ArrowDown\":\n target = addDays(date, 7);\n break;\n case \"Home\":\n target = addDays(date, -weekday);\n break;\n case \"End\":\n target = addDays(date, 6 - weekday);\n break;\n case \"PageUp\":\n case \"PageDown\": {\n const offset =\n (event.key === \"PageUp\" ? -1 : 1) * (event.shiftKey ? 12 : 1);\n const next = monthStart(date, offset);\n const lastDay = addDays(monthStart(next, 1), -1).getDate();\n target = localDate(\n next.getFullYear(),\n next.getMonth(),\n Math.min(date.getDate(), lastDay),\n );\n break;\n }\n default:\n return;\n }\n event.preventDefault();\n const nextKey = dayKey(target);\n pendingFocus.current = nextKey;\n setFocusedKey(nextKey);\n if (!sameMonth(target, month)) setMonth(monthStart(target));\n };\n\n const handlePanelKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const panel = event.currentTarget;\n if (\n !input ||\n event.key !== \"Tab\" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n !tabLeavesPanel(panel, event.target as Element, event.shiftKey)\n )\n return;\n event.preventDefault();\n const next = event.shiftKey\n ? input\n : (adjacentTabbable(\n input,\n tabContainer ?? input.ownerDocument.body,\n false,\n ) ?? input);\n next.focus();\n setOpen(false);\n };\n\n const heading = new Intl.DateTimeFormat(locale ?? language, {\n year: \"numeric\",\n month: \"long\",\n }).format(first);\n\n const displayValue = draft ?? current;\n\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions\n <div\n {...pickDataAttributes(rest)}\n {...hooks(\"date-picker\", \"root\", {\n state: open && !disabled && !readOnly ? \"open\" : \"closed\",\n disabled,\n readonly: readOnly,\n invalid,\n size,\n })}\n ref={setField}\n className={cn(styles.datePicker, className)}\n style={style}\n onClick={(e) => {\n if (e.target === input) toggle();\n }}\n >\n <FormControlContext.Provider value={null}>\n <Input\n ref={setInputRef}\n value={displayValue}\n placeholder={placeholder ?? t(\"datePicker.placeholder\")}\n id={fieldProps.id}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n aria-describedby={fieldProps[\"aria-describedby\"]}\n aria-invalid={invalid || undefined}\n aria-readonly={readOnly || undefined}\n required={required}\n readOnly={readOnly}\n onChange={(e) => handleInputChange(e.target.value)}\n onBlur={handleInputBlur}\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\") return;\n e.preventDefault();\n if (!open) {\n syncMonthFromValue(current);\n const focusTarget = current || todayKey;\n setFocusedKey(focusTarget);\n setFocusPanelOnOpen(true);\n setOpen(true);\n } else {\n panelRef.current\n ?.querySelector<HTMLElement>('[role=\"gridcell\"][tabindex=\"0\"]')\n ?.focus();\n }\n }}\n name={name}\n disabled={disabled}\n size={size}\n suffix={\n clearable && current && !disabled && !readOnly ? (\n <IconButton\n icon={<IconX aria-hidden focusable={false} />}\n size=\"small\"\n aria-label={t(\"datePicker.clear\")}\n onClick={handleClear}\n className={styles.clearButton}\n />\n ) : (\n <span\n className={styles.calendarIcon}\n aria-hidden=\"true\"\n {...hooks(\"date-picker\", \"icon\")}\n >\n <IconCalendar />\n </span>\n )\n }\n />\n </FormControlContext.Provider>\n <FloatingPanel\n ref={panelRef}\n open={open && !disabled && !readOnly}\n anchor={input}\n placement=\"bottom-start\"\n branches={() => [field]}\n onDismiss={() => setOpen(false)}\n returnFocusOnEscape={() => input}\n focusable\n role=\"dialog\"\n tabIndex={-1}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n className={styles.popup}\n onKeyDown={handlePanelKeyDown}\n {...hooks(\"date-picker\", \"content\", { state: \"open\" })}\n >\n <div className={styles.panel}>\n <div className={styles.header}>\n <h2 id={headingId} className={styles.heading} aria-live=\"polite\">\n {heading}\n </h2>\n <div className={styles.navGroup}>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.previousMonth\")}\n onClick={() => setMonth(monthStart(month, -1))}\n >\n <IconChevronLeft aria-hidden focusable={false} />\n </button>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.nextMonth\")}\n onClick={() => setMonth(monthStart(month, 1))}\n >\n <IconChevronRight aria-hidden focusable={false} />\n </button>\n </div>\n </div>\n <div role=\"grid\" aria-labelledby={headingId} className={styles.grid}>\n <div role=\"row\" className={styles.week}>\n {WEEKDAYS.map((day) => (\n <div role=\"columnheader\" key={day} className={styles.weekday}>\n {t(`monthCalendar.weekdays.${day}`)}\n </div>\n ))}\n </div>\n {Array.from({ length: 6 }, (_, week) => (\n <div role=\"row\" className={styles.week} key={week}>\n {days.slice(week * 7, week * 7 + 7).map((date) => {\n const key = dayKey(date);\n const selected = current === key;\n const outside = !sameMonth(date, month);\n const isToday = key === todayKey;\n const dayDisabled = isDayDisabled(key);\n return (\n <div\n role=\"gridcell\"\n key={key}\n className={styles.day}\n ref={(element) => {\n if (element) {\n cells.current.set(key, element);\n if (\n (focusPanelOnOpen && key === activeKey) ||\n pendingFocus.current === key\n ) {\n pendingFocus.current = null;\n element.focus();\n }\n } else {\n cells.current.delete(key);\n }\n }}\n data-date={key}\n data-outside={outside ? \"\" : undefined}\n aria-label={key}\n aria-selected={selected}\n aria-current={isToday ? \"date\" : undefined}\n aria-disabled={dayDisabled || undefined}\n tabIndex={!dayDisabled && key === activeKey ? 0 : -1}\n onFocus={() => setFocusedKey(key)}\n onClick={() => selectDate(date)}\n onKeyDown={(event) => handleDayKeyDown(event, date)}\n >\n {date.getDate()}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div className={styles.footer}>\n <button\n type=\"button\"\n className={styles.footerButton}\n disabled={isDayDisabled(todayKey)}\n onClick={() => selectDate(today)}\n >\n {t(\"datePicker.today\")}\n </button>\n {clearable && current && (\n <button\n type=\"button\"\n className={styles.footerButton}\n onClick={() => {\n handleClear();\n setOpen(false);\n }}\n >\n {t(\"datePicker.clear\")}\n </button>\n )}\n </div>\n </div>\n </FloatingPanel>\n </div>\n );\n};\n\nexport { DatePicker };\nexport default React.memo(DatePicker);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DatePicker.cjs","names":["useI18n","useId","useFormControlContext","useFormControlProps","useControllableState","useState","useMergedRefs","useRef","useLayerParent","parseDayKey","monthStart","dayKey","addDays","sameMonth","logicalArrowKey","localDate","tabLeavesPanel","adjacentTabbable","pickDataAttributes","hooks","cn","styles","FormControlContext","Input","IconButton","IconX","IconCalendar","FloatingPanel","IconChevronLeft","IconChevronRight","React","require_runtime","require_useI18n","require_stylingHooks","require_devWarnings","require_icons","require_mergeRefs","require_dataAttributes","require_useControllableState","require_context","require_useDismissableLayer","require_FloatingPanel","require_IconButton","require_Input","require_tabbing","require_datePicker_module","react","_minerva_core","react_jsx_runtime","_minerva_dom","WEEKDAYS","DatePicker","ariaLabel","ariaLabelledBy","ariaDescribedBy","requiredProp","readOnlyProp","invalidProp","disabledProp","rest","headingId","fc","fieldProps","disabled","readOnly","required","invalid","accessibleName","label","t","labelledBy","value","onChange","current","setCurrent","defaultValue","open","setOpen","onOpenChange","draft","setDraft","input","setInput","field","setField","setInputRef","ref","panelRef","tabContainer","initialDate","month","setMonth","focusedKey","setFocusedKey","focusPanelOnOpen","setFocusPanelOnOpen","cells","pendingFocus","isDayDisabled","minDate","key","maxDate","commit","next","syncMonthFromValue","parsed","val","handleInputChange","text","handleInputBlur","trimmed","handleClear","selectDate","date","toggle","prev","first","start","days","index","visibleKeys","today","todayKey","activeKey","monthKey","cell","handleDayKeyDown","event","target","weekday","offset","lastDay","nextKey","handlePanelKeyDown","panel","heading","locale","language","displayValue","className","placeholder","clearable","day","week","selected","outside","isToday","dayDisabled","element","DatePicker_default"],"sources":["../../../../../react/src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from \"react\";\nimport {\n addDays,\n dayKey,\n localDate,\n monthStart,\n parseDayKey,\n sameMonth,\n} from \"@minerva/core\";\nimport { cn } from \"../../utils/cn\";\nimport {\n IconCalendar,\n IconChevronLeft,\n IconChevronRight,\n IconX,\n} from \"../../internal/icons\";\nimport { Input } from \"../Input\";\nimport { IconButton } from \"../IconButton\";\nimport { FloatingPanel } from \"../../internal/FloatingPanel\";\nimport { useLayerParent } from \"../../internal/useDismissableLayer\";\nimport { adjacentTabbable, tabLeavesPanel } from \"../../internal/tabbing\";\nimport { useControllableState } from \"../../internal/useControllableState\";\nimport { warnControlledProps } from \"../../internal/devWarnings\";\nimport { useMergedRefs } from \"../../internal/mergeRefs\";\nimport useI18n from \"../../hooks/useI18n\";\nimport { pickDataAttributes } from \"../../internal/dataAttributes\";\nimport { logicalArrowKey } from \"../../internal/direction\";\nimport {\n FormControlContext,\n useFormControlContext,\n useFormControlProps,\n} from \"../FormControl/context\";\nimport type { DatePickerProps } from \"./types\";\nimport { hooks } from \"../../internal/stylingHooks\";\nimport styles from \"./datePicker.module.scss\";\n\nconst WEEKDAYS = [\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"] as const;\n\n/**\n * DatePicker: type a `\"YYYY-MM-DD\"` date or pick a day from a popup month\n * calendar grid. Works controlled (`value` + `onChange`) or uncontrolled\n * (`defaultValue`). Inside a FormControl the input picks up the field's id,\n * label, description, invalid, required, disabled and read-only state\n * (explicit props win).\n */\nconst DatePicker = ({\n ref,\n value,\n defaultValue,\n onChange,\n placeholder,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n id,\n required: requiredProp,\n readOnly: readOnlyProp,\n invalid: invalidProp,\n name = \"date-picker\",\n disabled: disabledProp,\n clearable = true,\n size = \"medium\",\n minDate,\n maxDate,\n locale,\n className = \"\",\n style,\n onOpenChange,\n ...rest\n}: DatePickerProps) => {\n const { t, language } = useI18n();\n const headingId = useId();\n const fc = useFormControlContext();\n const fieldProps = useFormControlProps({\n id,\n \"aria-describedby\": ariaDescribedBy,\n });\n const disabled = disabledProp ?? fc?.disabled ?? false;\n const readOnly = readOnlyProp ?? fc?.readOnly ?? false;\n const required = requiredProp ?? fc?.required ?? false;\n const invalid = invalidProp ?? fc?.invalid ?? false;\n const accessibleName = label ?? ariaLabel ?? t(\"datePicker.label\");\n const labelledBy =\n ariaLabelledBy ?? (fc && !label && !ariaLabel ? fc.labelId : undefined);\n\n if (process.env.NODE_ENV !== \"production\") {\n warnControlledProps(\"DatePicker\", {\n prop: \"value\",\n value: value === null ? \"\" : value,\n defaultProp: \"defaultValue\",\n defaultValue,\n handlerProp: \"onChange\",\n handler: onChange,\n locked: disabled || readOnly,\n lockHint: \"set `disabled` / `readOnly`\",\n });\n }\n\n const normalizedValue = value === null ? \"\" : value;\n const [current, setCurrent] = useControllableState<string>({\n value: normalizedValue,\n defaultValue: defaultValue ?? \"\",\n name: \"DatePicker\",\n });\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: onOpenChange,\n name: \"DatePicker\",\n prop: \"open\",\n });\n\n const [draft, setDraft] = useState<string | null>(null);\n const [input, setInput] = useState<HTMLInputElement | null>(null);\n const [field, setField] = useState<HTMLDivElement | null>(null);\n const setInputRef = useMergedRefs<HTMLInputElement>(setInput, ref);\n const panelRef = useRef<HTMLDivElement>(null);\n const tabContainer = useLayerParent();\n\n const initialDate = parseDayKey(current || \"\") ?? new Date();\n const [month, setMonth] = useState<Date>(() => monthStart(initialDate));\n const [focusedKey, setFocusedKey] = useState(\"\");\n const [focusPanelOnOpen, setFocusPanelOnOpen] = useState(false);\n const cells = useRef(new Map<string, HTMLDivElement>());\n const pendingFocus = useRef<string | null>(null);\n\n const isDayDisabled = (key: string) => {\n if (minDate && key < minDate) return true;\n if (maxDate && key > maxDate) return true;\n return false;\n };\n\n const commit = (next: string) => {\n setCurrent(next);\n onChange?.(next);\n };\n\n const syncMonthFromValue = (val: string) => {\n const parsed = parseDayKey(val);\n if (parsed) setMonth(monthStart(parsed));\n };\n\n const handleInputChange = (text: string) => {\n setDraft(text);\n if (text === \"\") {\n commit(\"\");\n return;\n }\n const parsed = parseDayKey(text, true);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key)) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n };\n\n const handleInputBlur = () => {\n if (draft === null) return;\n const trimmed = draft.trim();\n if (trimmed === \"\") {\n if (current) commit(\"\");\n } else {\n const parsed = parseDayKey(trimmed, false);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key) && key !== current) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n }\n setDraft(null);\n };\n\n const handleClear = () => {\n setDraft(null);\n commit(\"\");\n input?.focus();\n };\n\n const selectDate = (date: Date) => {\n const key = dayKey(date);\n if (disabled || readOnly || isDayDisabled(key)) return;\n setDraft(null);\n commit(key);\n setMonth(monthStart(date));\n setOpen(false);\n input?.focus();\n };\n\n const toggle = () => {\n if (disabled || readOnly) return;\n setFocusPanelOnOpen(false);\n if (!open) syncMonthFromValue(current);\n setOpen((prev) => !prev);\n };\n\n const first = monthStart(month);\n const start = addDays(first, -((first.getDay() + 6) % 7));\n const days = Array.from({ length: 42 }, (_, index) => addDays(start, index));\n const visibleKeys = days.map(dayKey);\n const today = new Date();\n const todayKey = dayKey(today);\n // Roving Tab stop: never a disabled day while the view has an enabled one\n // (e.g. a month cut by minDate), else the grid has no Tab entry.\n const activeKey = [\n focusedKey,\n current,\n sameMonth(today, month) ? todayKey : \"\",\n dayKey(first),\n ...visibleKeys,\n ].find((key) => key && visibleKeys.includes(key) && !isDayDisabled(key));\n const monthKey = dayKey(first);\n\n useEffect(() => {\n if (!open || disabled || !pendingFocus.current) return;\n const cell = cells.current.get(pendingFocus.current);\n if (cell) {\n pendingFocus.current = null;\n cell.focus();\n }\n }, [open, monthKey, focusedKey, disabled]);\n\n const handleDayKeyDown = (\n event: React.KeyboardEvent<HTMLDivElement>,\n date: Date,\n ) => {\n if (disabled || readOnly) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (!event.repeat) selectDate(date);\n return;\n }\n let target: Date;\n const weekday = (date.getDay() + 6) % 7;\n switch (logicalArrowKey(event.key, event.currentTarget)) {\n case \"ArrowLeft\":\n target = addDays(date, -1);\n break;\n case \"ArrowRight\":\n target = addDays(date, 1);\n break;\n case \"ArrowUp\":\n target = addDays(date, -7);\n break;\n case \"ArrowDown\":\n target = addDays(date, 7);\n break;\n case \"Home\":\n target = addDays(date, -weekday);\n break;\n case \"End\":\n target = addDays(date, 6 - weekday);\n break;\n case \"PageUp\":\n case \"PageDown\": {\n const offset =\n (event.key === \"PageUp\" ? -1 : 1) * (event.shiftKey ? 12 : 1);\n const next = monthStart(date, offset);\n const lastDay = addDays(monthStart(next, 1), -1).getDate();\n target = localDate(\n next.getFullYear(),\n next.getMonth(),\n Math.min(date.getDate(), lastDay),\n );\n break;\n }\n default:\n return;\n }\n event.preventDefault();\n const nextKey = dayKey(target);\n pendingFocus.current = nextKey;\n setFocusedKey(nextKey);\n if (!sameMonth(target, month)) setMonth(monthStart(target));\n };\n\n const handlePanelKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const panel = event.currentTarget;\n if (\n !input ||\n event.key !== \"Tab\" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n !tabLeavesPanel(panel, event.target as Element, event.shiftKey)\n )\n return;\n event.preventDefault();\n const next = event.shiftKey\n ? input\n : (adjacentTabbable(\n input,\n tabContainer ?? input.ownerDocument.body,\n false,\n ) ?? input);\n next.focus();\n setOpen(false);\n };\n\n const heading = new Intl.DateTimeFormat(locale ?? language, {\n year: \"numeric\",\n month: \"long\",\n }).format(first);\n\n const displayValue = draft ?? current;\n\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions\n <div\n {...pickDataAttributes(rest)}\n {...hooks(\"date-picker\", \"root\", {\n state: open && !disabled && !readOnly ? \"open\" : \"closed\",\n disabled,\n readonly: readOnly,\n invalid,\n size,\n })}\n ref={setField}\n className={cn(styles.datePicker, className)}\n style={style}\n onClick={(e) => {\n if (e.target === input) toggle();\n }}\n >\n <FormControlContext.Provider value={null}>\n <Input\n ref={setInputRef}\n value={displayValue}\n placeholder={placeholder ?? t(\"datePicker.placeholder\")}\n id={fieldProps.id}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n aria-describedby={fieldProps[\"aria-describedby\"]}\n aria-invalid={invalid || undefined}\n aria-readonly={readOnly || undefined}\n required={required}\n readOnly={readOnly}\n onChange={(e) => handleInputChange(e.target.value)}\n onBlur={handleInputBlur}\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\") return;\n e.preventDefault();\n if (!open) {\n syncMonthFromValue(current);\n const focusTarget = current || todayKey;\n setFocusedKey(focusTarget);\n setFocusPanelOnOpen(true);\n setOpen(true);\n } else {\n panelRef.current\n ?.querySelector<HTMLElement>('[role=\"gridcell\"][tabindex=\"0\"]')\n ?.focus();\n }\n }}\n name={name}\n disabled={disabled}\n size={size}\n suffix={\n clearable && current && !disabled && !readOnly ? (\n <IconButton\n icon={<IconX aria-hidden focusable={false} />}\n size=\"small\"\n aria-label={t(\"datePicker.clear\")}\n onClick={handleClear}\n className={styles.clearButton}\n />\n ) : (\n <span\n className={styles.calendarIcon}\n aria-hidden=\"true\"\n {...hooks(\"date-picker\", \"icon\")}\n >\n <IconCalendar />\n </span>\n )\n }\n />\n </FormControlContext.Provider>\n <FloatingPanel\n ref={panelRef}\n open={open && !disabled && !readOnly}\n anchor={input}\n placement=\"bottom-start\"\n branches={() => [field]}\n onDismiss={() => setOpen(false)}\n returnFocusOnEscape={() => input}\n focusable\n role=\"dialog\"\n tabIndex={-1}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n className={styles.popup}\n onKeyDown={handlePanelKeyDown}\n {...hooks(\"date-picker\", \"content\", { state: \"open\" })}\n >\n <div className={styles.panel}>\n <div className={styles.header}>\n <h2 id={headingId} className={styles.heading} aria-live=\"polite\">\n {heading}\n </h2>\n <div className={styles.navGroup}>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.previousMonth\")}\n onClick={() => setMonth(monthStart(month, -1))}\n >\n <IconChevronLeft aria-hidden focusable={false} />\n </button>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.nextMonth\")}\n onClick={() => setMonth(monthStart(month, 1))}\n >\n <IconChevronRight aria-hidden focusable={false} />\n </button>\n </div>\n </div>\n <div role=\"grid\" aria-labelledby={headingId} className={styles.grid}>\n <div role=\"row\" className={styles.week}>\n {WEEKDAYS.map((day) => (\n <div role=\"columnheader\" key={day} className={styles.weekday}>\n {t(`monthCalendar.weekdays.${day}`)}\n </div>\n ))}\n </div>\n {Array.from({ length: 6 }, (_, week) => (\n <div role=\"row\" className={styles.week} key={week}>\n {days.slice(week * 7, week * 7 + 7).map((date) => {\n const key = dayKey(date);\n const selected = current === key;\n const outside = !sameMonth(date, month);\n const isToday = key === todayKey;\n const dayDisabled = isDayDisabled(key);\n return (\n <div\n role=\"gridcell\"\n key={key}\n className={styles.day}\n ref={(element) => {\n if (element) {\n cells.current.set(key, element);\n if (\n (focusPanelOnOpen && key === activeKey) ||\n pendingFocus.current === key\n ) {\n pendingFocus.current = null;\n element.focus();\n }\n } else {\n cells.current.delete(key);\n }\n }}\n data-date={key}\n data-outside={outside ? \"\" : undefined}\n aria-label={key}\n aria-selected={selected}\n aria-current={isToday ? \"date\" : undefined}\n aria-disabled={dayDisabled || undefined}\n tabIndex={!dayDisabled && key === activeKey ? 0 : -1}\n onFocus={() => setFocusedKey(key)}\n onClick={() => selectDate(date)}\n onKeyDown={(event) => handleDayKeyDown(event, date)}\n >\n {date.getDate()}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div className={styles.footer}>\n <button\n type=\"button\"\n className={styles.footerButton}\n disabled={isDayDisabled(todayKey)}\n onClick={() => selectDate(today)}\n >\n {t(\"datePicker.today\")}\n </button>\n {clearable && current && (\n <button\n type=\"button\"\n className={styles.footerButton}\n onClick={() => {\n handleClear();\n setOpen(false);\n }}\n >\n {t(\"datePicker.clear\")}\n </button>\n )}\n </div>\n </div>\n </FloatingPanel>\n </div>\n );\n};\n\nexport { DatePicker };\nexport default React.memo(DatePicker);\n"],"mappings":"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"}
|
|
@@ -91,8 +91,9 @@ var ve = [
|
|
|
91
91
|
He,
|
|
92
92
|
F,
|
|
93
93
|
m(Z, H) ? Q : "",
|
|
94
|
-
d(X)
|
|
95
|
-
|
|
94
|
+
d(X),
|
|
95
|
+
...Qe
|
|
96
|
+
].find((e) => e && Qe.includes(e) && !q(e)), $e = d(X);
|
|
96
97
|
he(() => {
|
|
97
98
|
if (!I || A || !K.current) return;
|
|
98
99
|
let e = G.current.get(K.current);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.js","names":["styles","IconButton","useI18n","IconButton_default","datePicker_module_default","React","WEEKDAYS","DatePicker","ariaLabel","ariaLabelledBy","ariaDescribedBy","requiredProp","readOnlyProp","invalidProp","disabledProp","rest","headingId","useId","fc","useFormControlContext","fieldProps","useFormControlProps","disabled","readOnly","required","invalid","accessibleName","label","t","labelledBy","warnControlledProps","value","onChange","current","setCurrent","useControllableState","defaultValue","open","setOpen","onOpenChange","draft","setDraft","useState","input","setInput","field","setField","setInputRef","useMergedRefs","ref","panelRef","useRef","tabContainer","useLayerParent","initialDate","parseDayKey","month","setMonth","monthStart","focusedKey","setFocusedKey","focusPanelOnOpen","setFocusPanelOnOpen","cells","pendingFocus","isDayDisabled","minDate","key","maxDate","commit","next","syncMonthFromValue","parsed","val","handleInputChange","text","dayKey","handleInputBlur","trimmed","handleClear","selectDate","date","toggle","prev","first","start","addDays","days","index","visibleKeys","today","todayKey","activeKey","sameMonth","monthKey","cell","handleDayKeyDown","event","target","weekday","logicalArrowKey","offset","lastDay","localDate","nextKey","handlePanelKeyDown","panel","tabLeavesPanel","adjacentTabbable","heading","locale","language","displayValue","pickDataAttributes","hooks","cn","className","FormControlContext","Input","placeholder","clearable","IconX","IconCalendar","FloatingPanel","IconChevronLeft","IconChevronRight","day","week","selected","outside","isToday","dayDisabled","element","DatePicker_default"],"sources":["../../../../../react/src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from \"react\";\nimport {\n addDays,\n dayKey,\n localDate,\n monthStart,\n parseDayKey,\n sameMonth,\n} from \"@minerva/core\";\nimport { cn } from \"../../utils/cn\";\nimport {\n IconCalendar,\n IconChevronLeft,\n IconChevronRight,\n IconX,\n} from \"../../internal/icons\";\nimport { Input } from \"../Input\";\nimport { IconButton } from \"../IconButton\";\nimport { FloatingPanel } from \"../../internal/FloatingPanel\";\nimport { useLayerParent } from \"../../internal/useDismissableLayer\";\nimport { adjacentTabbable, tabLeavesPanel } from \"../../internal/tabbing\";\nimport { useControllableState } from \"../../internal/useControllableState\";\nimport { warnControlledProps } from \"../../internal/devWarnings\";\nimport { useMergedRefs } from \"../../internal/mergeRefs\";\nimport useI18n from \"../../hooks/useI18n\";\nimport { pickDataAttributes } from \"../../internal/dataAttributes\";\nimport { logicalArrowKey } from \"../../internal/direction\";\nimport {\n FormControlContext,\n useFormControlContext,\n useFormControlProps,\n} from \"../FormControl/context\";\nimport type { DatePickerProps } from \"./types\";\nimport { hooks } from \"../../internal/stylingHooks\";\nimport styles from \"./datePicker.module.scss\";\n\nconst WEEKDAYS = [\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"] as const;\n\n/**\n * DatePicker: type a `\"YYYY-MM-DD\"` date or pick a day from a popup month\n * calendar grid. Works controlled (`value` + `onChange`) or uncontrolled\n * (`defaultValue`). Inside a FormControl the input picks up the field's id,\n * label, description, invalid, required, disabled and read-only state\n * (explicit props win).\n */\nconst DatePicker = ({\n ref,\n value,\n defaultValue,\n onChange,\n placeholder,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n id,\n required: requiredProp,\n readOnly: readOnlyProp,\n invalid: invalidProp,\n name = \"date-picker\",\n disabled: disabledProp,\n clearable = true,\n size = \"medium\",\n minDate,\n maxDate,\n locale,\n className = \"\",\n style,\n onOpenChange,\n ...rest\n}: DatePickerProps) => {\n const { t, language } = useI18n();\n const headingId = useId();\n const fc = useFormControlContext();\n const fieldProps = useFormControlProps({\n id,\n \"aria-describedby\": ariaDescribedBy,\n });\n const disabled = disabledProp ?? fc?.disabled ?? false;\n const readOnly = readOnlyProp ?? fc?.readOnly ?? false;\n const required = requiredProp ?? fc?.required ?? false;\n const invalid = invalidProp ?? fc?.invalid ?? false;\n const accessibleName = label ?? ariaLabel ?? t(\"datePicker.label\");\n const labelledBy =\n ariaLabelledBy ?? (fc && !label && !ariaLabel ? fc.labelId : undefined);\n\n if (process.env.NODE_ENV !== \"production\") {\n warnControlledProps(\"DatePicker\", {\n prop: \"value\",\n value: value === null ? \"\" : value,\n defaultProp: \"defaultValue\",\n defaultValue,\n handlerProp: \"onChange\",\n handler: onChange,\n locked: disabled || readOnly,\n lockHint: \"set `disabled` / `readOnly`\",\n });\n }\n\n const normalizedValue = value === null ? \"\" : value;\n const [current, setCurrent] = useControllableState<string>({\n value: normalizedValue,\n defaultValue: defaultValue ?? \"\",\n name: \"DatePicker\",\n });\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: onOpenChange,\n name: \"DatePicker\",\n prop: \"open\",\n });\n\n const [draft, setDraft] = useState<string | null>(null);\n const [input, setInput] = useState<HTMLInputElement | null>(null);\n const [field, setField] = useState<HTMLDivElement | null>(null);\n const setInputRef = useMergedRefs<HTMLInputElement>(setInput, ref);\n const panelRef = useRef<HTMLDivElement>(null);\n const tabContainer = useLayerParent();\n\n const initialDate = parseDayKey(current || \"\") ?? new Date();\n const [month, setMonth] = useState<Date>(() => monthStart(initialDate));\n const [focusedKey, setFocusedKey] = useState(\"\");\n const [focusPanelOnOpen, setFocusPanelOnOpen] = useState(false);\n const cells = useRef(new Map<string, HTMLDivElement>());\n const pendingFocus = useRef<string | null>(null);\n\n const isDayDisabled = (key: string) => {\n if (minDate && key < minDate) return true;\n if (maxDate && key > maxDate) return true;\n return false;\n };\n\n const commit = (next: string) => {\n setCurrent(next);\n onChange?.(next);\n };\n\n const syncMonthFromValue = (val: string) => {\n const parsed = parseDayKey(val);\n if (parsed) setMonth(monthStart(parsed));\n };\n\n const handleInputChange = (text: string) => {\n setDraft(text);\n if (text === \"\") {\n commit(\"\");\n return;\n }\n const parsed = parseDayKey(text, true);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key)) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n };\n\n const handleInputBlur = () => {\n if (draft === null) return;\n const trimmed = draft.trim();\n if (trimmed === \"\") {\n if (current) commit(\"\");\n } else {\n const parsed = parseDayKey(trimmed, false);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key) && key !== current) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n }\n setDraft(null);\n };\n\n const handleClear = () => {\n setDraft(null);\n commit(\"\");\n input?.focus();\n };\n\n const selectDate = (date: Date) => {\n const key = dayKey(date);\n if (disabled || readOnly || isDayDisabled(key)) return;\n setDraft(null);\n commit(key);\n setMonth(monthStart(date));\n setOpen(false);\n input?.focus();\n };\n\n const toggle = () => {\n if (disabled || readOnly) return;\n setFocusPanelOnOpen(false);\n if (!open) syncMonthFromValue(current);\n setOpen((prev) => !prev);\n };\n\n const first = monthStart(month);\n const start = addDays(first, -((first.getDay() + 6) % 7));\n const days = Array.from({ length: 42 }, (_, index) => addDays(start, index));\n const visibleKeys = days.map(dayKey);\n const today = new Date();\n const todayKey = dayKey(today);\n const activeKey = [\n focusedKey,\n current,\n sameMonth(today, month) ? todayKey : \"\",\n dayKey(first),\n ].find((key) => key && visibleKeys.includes(key));\n const monthKey = dayKey(first);\n\n useEffect(() => {\n if (!open || disabled || !pendingFocus.current) return;\n const cell = cells.current.get(pendingFocus.current);\n if (cell) {\n pendingFocus.current = null;\n cell.focus();\n }\n }, [open, monthKey, focusedKey, disabled]);\n\n const handleDayKeyDown = (\n event: React.KeyboardEvent<HTMLDivElement>,\n date: Date,\n ) => {\n if (disabled || readOnly) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (!event.repeat) selectDate(date);\n return;\n }\n let target: Date;\n const weekday = (date.getDay() + 6) % 7;\n switch (logicalArrowKey(event.key, event.currentTarget)) {\n case \"ArrowLeft\":\n target = addDays(date, -1);\n break;\n case \"ArrowRight\":\n target = addDays(date, 1);\n break;\n case \"ArrowUp\":\n target = addDays(date, -7);\n break;\n case \"ArrowDown\":\n target = addDays(date, 7);\n break;\n case \"Home\":\n target = addDays(date, -weekday);\n break;\n case \"End\":\n target = addDays(date, 6 - weekday);\n break;\n case \"PageUp\":\n case \"PageDown\": {\n const offset =\n (event.key === \"PageUp\" ? -1 : 1) * (event.shiftKey ? 12 : 1);\n const next = monthStart(date, offset);\n const lastDay = addDays(monthStart(next, 1), -1).getDate();\n target = localDate(\n next.getFullYear(),\n next.getMonth(),\n Math.min(date.getDate(), lastDay),\n );\n break;\n }\n default:\n return;\n }\n event.preventDefault();\n const nextKey = dayKey(target);\n pendingFocus.current = nextKey;\n setFocusedKey(nextKey);\n if (!sameMonth(target, month)) setMonth(monthStart(target));\n };\n\n const handlePanelKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const panel = event.currentTarget;\n if (\n !input ||\n event.key !== \"Tab\" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n !tabLeavesPanel(panel, event.target as Element, event.shiftKey)\n )\n return;\n event.preventDefault();\n const next = event.shiftKey\n ? input\n : (adjacentTabbable(\n input,\n tabContainer ?? input.ownerDocument.body,\n false,\n ) ?? input);\n next.focus();\n setOpen(false);\n };\n\n const heading = new Intl.DateTimeFormat(locale ?? language, {\n year: \"numeric\",\n month: \"long\",\n }).format(first);\n\n const displayValue = draft ?? current;\n\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions\n <div\n {...pickDataAttributes(rest)}\n {...hooks(\"date-picker\", \"root\", {\n state: open && !disabled && !readOnly ? \"open\" : \"closed\",\n disabled,\n readonly: readOnly,\n invalid,\n size,\n })}\n ref={setField}\n className={cn(styles.datePicker, className)}\n style={style}\n onClick={(e) => {\n if (e.target === input) toggle();\n }}\n >\n <FormControlContext.Provider value={null}>\n <Input\n ref={setInputRef}\n value={displayValue}\n placeholder={placeholder ?? t(\"datePicker.placeholder\")}\n id={fieldProps.id}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n aria-describedby={fieldProps[\"aria-describedby\"]}\n aria-invalid={invalid || undefined}\n aria-readonly={readOnly || undefined}\n required={required}\n readOnly={readOnly}\n onChange={(e) => handleInputChange(e.target.value)}\n onBlur={handleInputBlur}\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\") return;\n e.preventDefault();\n if (!open) {\n syncMonthFromValue(current);\n const focusTarget = current || todayKey;\n setFocusedKey(focusTarget);\n setFocusPanelOnOpen(true);\n setOpen(true);\n } else {\n panelRef.current\n ?.querySelector<HTMLElement>('[role=\"gridcell\"][tabindex=\"0\"]')\n ?.focus();\n }\n }}\n name={name}\n disabled={disabled}\n size={size}\n suffix={\n clearable && current && !disabled && !readOnly ? (\n <IconButton\n icon={<IconX aria-hidden focusable={false} />}\n size=\"small\"\n aria-label={t(\"datePicker.clear\")}\n onClick={handleClear}\n className={styles.clearButton}\n />\n ) : (\n <span\n className={styles.calendarIcon}\n aria-hidden=\"true\"\n {...hooks(\"date-picker\", \"icon\")}\n >\n <IconCalendar />\n </span>\n )\n }\n />\n </FormControlContext.Provider>\n <FloatingPanel\n ref={panelRef}\n open={open && !disabled && !readOnly}\n anchor={input}\n placement=\"bottom-start\"\n branches={() => [field]}\n onDismiss={() => setOpen(false)}\n returnFocusOnEscape={() => input}\n focusable\n role=\"dialog\"\n tabIndex={-1}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n className={styles.popup}\n onKeyDown={handlePanelKeyDown}\n {...hooks(\"date-picker\", \"content\", { state: \"open\" })}\n >\n <div className={styles.panel}>\n <div className={styles.header}>\n <h2 id={headingId} className={styles.heading} aria-live=\"polite\">\n {heading}\n </h2>\n <div className={styles.navGroup}>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.previousMonth\")}\n onClick={() => setMonth(monthStart(month, -1))}\n >\n <IconChevronLeft aria-hidden focusable={false} />\n </button>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.nextMonth\")}\n onClick={() => setMonth(monthStart(month, 1))}\n >\n <IconChevronRight aria-hidden focusable={false} />\n </button>\n </div>\n </div>\n <div role=\"grid\" aria-labelledby={headingId} className={styles.grid}>\n <div role=\"row\" className={styles.week}>\n {WEEKDAYS.map((day) => (\n <div role=\"columnheader\" key={day} className={styles.weekday}>\n {t(`monthCalendar.weekdays.${day}`)}\n </div>\n ))}\n </div>\n {Array.from({ length: 6 }, (_, week) => (\n <div role=\"row\" className={styles.week} key={week}>\n {days.slice(week * 7, week * 7 + 7).map((date) => {\n const key = dayKey(date);\n const selected = current === key;\n const outside = !sameMonth(date, month);\n const isToday = key === todayKey;\n const dayDisabled = isDayDisabled(key);\n return (\n <div\n role=\"gridcell\"\n key={key}\n className={styles.day}\n ref={(element) => {\n if (element) {\n cells.current.set(key, element);\n if (\n (focusPanelOnOpen && key === activeKey) ||\n pendingFocus.current === key\n ) {\n pendingFocus.current = null;\n element.focus();\n }\n } else {\n cells.current.delete(key);\n }\n }}\n data-date={key}\n data-outside={outside ? \"\" : undefined}\n aria-label={key}\n aria-selected={selected}\n aria-current={isToday ? \"date\" : undefined}\n aria-disabled={dayDisabled || undefined}\n tabIndex={!dayDisabled && key === activeKey ? 0 : -1}\n onFocus={() => setFocusedKey(key)}\n onClick={() => selectDate(date)}\n onKeyDown={(event) => handleDayKeyDown(event, date)}\n >\n {date.getDate()}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div className={styles.footer}>\n <button\n type=\"button\"\n className={styles.footerButton}\n disabled={isDayDisabled(todayKey)}\n onClick={() => selectDate(today)}\n >\n {t(\"datePicker.today\")}\n </button>\n {clearable && current && (\n <button\n type=\"button\"\n className={styles.footerButton}\n onClick={() => {\n handleClear();\n setOpen(false);\n }}\n >\n {t(\"datePicker.clear\")}\n </button>\n )}\n </div>\n </div>\n </FloatingPanel>\n </div>\n );\n};\n\nexport { DatePicker };\nexport default React.memo(DatePicker);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAMM,KAAW;CAAC;CAAO;CAAO;CAAO;CAAO;CAAO;CAAO;AAAK,GAS3DC,KAAc,EAClB,QACA,UACA,iBACA,aACA,iBACA,UACA,cAAcC,GACd,mBAAmBC,IACnB,oBAAoBC,IACpB,QACA,UAAUC,IACV,UAAUC,IACV,SAASC,IACT,WAAO,eACP,UAAUC,IACV,eAAY,IACZ,UAAO,UACP,YACA,YACA,YACA,gBAAY,IACZ,WACA,kBACA,GAAGC,SACkB;CACrB,IAAM,EAAE,MAAG,iBAAab,EAAQ,GAC1Bc,IAAYC,GAAM,GAClBC,IAAKC,GAAsB,GAC3BC,IAAaC,GAAoB;EACrC;EACA,oBAAoBX;CACtB,CAAC,GACKY,IAAWR,MAAgBI,GAAI,YAAY,IAC3CK,IAAWX,MAAgBM,GAAI,YAAY,IAC3CM,KAAWb,MAAgBO,GAAI,YAAY,IAC3CO,IAAUZ,MAAeK,GAAI,WAAW,IACxCQ,IAAiBC,KAASnB,KAAaoB,EAAE,kBAAkB,GAC3DC,IACJpB,OAAmBS,KAAM,CAACS,KAAS,CAACnB,IAAYU,EAAG,UAAU,KAAA;CAE/D,AAAA,QAAA,IAAA,aAA6B,gBAC3BY,EAAoB,cAAc;EAChC,MAAM;EACN,OAAOC,MAAU,OAAO,KAAKA;EAC7B,aAAa;EACb;EACA,aAAa;EACb,SAASC;EACT,QAAQV,KAAYC;EACpB,UAAU;CACZ,CAAC;CAIH,IAAM,CAACU,GAASC,MAAcC,GAA6B;EACzD,OAFsBJ,MAAU,OAAO,KAAKA;EAG5C,cAAcK,KAAgB;EAC9B,MAAM;CACR,CAAC,GACK,CAACC,GAAMC,KAAWH,GAAqB;EAC3C,cAAc;EACd,UAAUI;EACV,MAAM;EACN,MAAM;CACR,CAAC,GAEK,CAACC,GAAOC,KAAYC,EAAwB,IAAI,GAChD,CAACC,GAAOC,MAAYF,EAAkC,IAAI,GAC1D,CAACG,IAAOC,MAAYJ,EAAgC,IAAI,GACxDK,KAAcC,GAAgCJ,IAAUK,CAAG,GAC3DC,IAAWC,EAAuB,IAAI,GACtCC,KAAeC,GAAe,GAE9BC,KAAcC,EAAYtB,KAAW,EAAE,qBAAK,IAAI,KAAK,GACrD,CAACuB,GAAOC,KAAYf,QAAqBgB,EAAWJ,EAAW,CAAC,GAChE,CAACK,IAAYC,KAAiBlB,EAAS,EAAE,GACzC,CAACmB,IAAkBC,MAAuBpB,EAAS,EAAK,GACxDqB,IAAQZ,kBAAO,IAAI,IAA4B,CAAC,GAChDa,IAAeb,EAAsB,IAAI,GAEzCc,KAAiB,MAErB,GADIC,KAAWC,IAAMD,KACjBE,KAAWD,IAAMC,IAIjBC,KAAU,MAAiB;EAE/B,AADAnC,GAAWoC,CAAI,GACftC,IAAWsC,CAAI;CACjB,GAEMC,MAAsB,MAAgB;EAC1C,IAAMC,IAASjB,EAAYkB,CAAG;EAC9B,AAAID,KAAQf,EAASC,EAAWc,CAAM,CAAC;CACzC,GAEME,MAAqB,MAAiB;EAE1C,IADAjC,EAASkC,CAAI,GACTA,MAAS,IAAI;GACf,EAAO,EAAE;GACT;EACF;EACA,IAAMH,IAASjB,EAAYoB,GAAM,EAAI;EACrC,IAAIH,GAAQ;GACV,IAAML,IAAMS,EAAOJ,CAAM;GACzB,AAAKP,EAAcE,CAAG,MACpBE,EAAOF,CAAG,GACVV,EAASC,EAAWc,CAAM,CAAC;EAE/B;CACF,GAEMK,WAAwB;EAC5B,IAAIrC,MAAU,MAAM;EACpB,IAAMsC,IAAUtC,EAAM,KAAK;EAC3B,IAAIsC,MAAY,IACV,AAAA7C,KAASoC,EAAO,EAAE;OACjB;GACL,IAAMG,IAASjB,EAAYuB,GAAS,EAAK;GACzC,IAAIN,GAAQ;IACV,IAAML,IAAMS,EAAOJ,CAAM;IACzB,AAAI,CAACP,EAAcE,CAAG,KAAKA,MAAQlC,MACjCoC,EAAOF,CAAG,GACVV,EAASC,EAAWc,CAAM,CAAC;GAE/B;EACF;EACA,EAAS,IAAI;CACf,GAEMO,WAAoB;EAGxB,AAFAtC,EAAS,IAAI,GACb4B,EAAO,EAAE,GACT1B,GAAO,MAAM;CACf,GAEMqC,KAAc,MAAe;EACjC,IAAMb,IAAMS,EAAOK,CAAI;EACvB,AAAI3D,KAAYC,KAAY0C,EAAcE,CAAG,MAC7C1B,EAAS,IAAI,GACb4B,EAAOF,CAAG,GACVV,EAASC,EAAWuB,CAAI,CAAC,GACzB3C,EAAQ,EAAK,GACbK,GAAO,MAAM;CACf,GAEMuC,WAAe;EACnB,AAAI5D,KAAYC,MAChBuC,GAAoB,EAAK,GACpBzB,KAAMkC,GAAmBtC,CAAO,GACrCK,GAAS,MAAS,CAAC6C,CAAI;CACzB,GAEMC,IAAQ1B,EAAWF,CAAK,GACxB6B,KAAQC,EAAQF,GAAO,GAAGA,EAAM,OAAO,IAAI,KAAK,EAAE,GAClDG,KAAO,MAAM,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAUD,EAAQD,IAAOG,CAAK,CAAC,GACrEC,KAAcF,GAAK,IAAIX,CAAM,GAC7Bc,oBAAQ,IAAI,KAAK,GACjBC,IAAWf,EAAOc,CAAK,GACvBE,IAAY;EAChBjC;EACA1B;EACA4D,EAAUH,GAAOlC,CAAK,IAAImC,IAAW;EACrCf,EAAOQ,CAAK;CACd,CAAC,CAAC,MAAM,MAAQjB,KAAOsB,GAAY,SAAStB,CAAG,CAAC,GAC1C2B,KAAWlB,EAAOQ,CAAK;CAE7B,SAAgB;EACd,IAAI,CAAC/C,KAAQf,KAAY,CAAC0C,EAAa,SAAS;EAChD,IAAM+B,IAAOhC,EAAM,QAAQ,IAAIC,EAAa,OAAO;EACnD,AAAI+B,MACF,EAAa,UAAU,MACvBA,EAAK,MAAM;CAEf,GAAG;EAAC1D;EAAMyD;EAAUnC;EAAYrC;CAAQ,CAAC;CAEzC,IAAM0E,MACJ,GACA,MACG;EACH,IAAI1E,KAAYC,GAAU;EAC1B,IAAI0E,EAAM,QAAQ,WAAWA,EAAM,QAAQ,KAAK;GAE9C,AADAA,EAAM,eAAe,GAChBA,EAAM,UAAQjB,EAAWC,CAAI;GAClC;EACF;EACA,IAAIiB,GACEC,KAAWlB,EAAK,OAAO,IAAI,KAAK;EACtC,QAAQmB,GAAgBH,EAAM,KAAKA,EAAM,aAAa,GAAtD;GACE,KAAK;IACH,IAASX,EAAQL,GAAM,EAAE;IACzB;GACF,KAAK;IACH,IAASK,EAAQL,GAAM,CAAC;IACxB;GACF,KAAK;IACH,IAASK,EAAQL,GAAM,EAAE;IACzB;GACF,KAAK;IACH,IAASK,EAAQL,GAAM,CAAC;IACxB;GACF,KAAK;IACH,IAASK,EAAQL,GAAM,CAACkB,CAAO;IAC/B;GACF,KAAK;IACH,IAASb,EAAQL,GAAM,IAAIkB,CAAO;IAClC;GACF,KAAK;GACL,KAAK,YAAY;IACf,IAAME,KACHJ,EAAM,QAAQ,WAAW,KAAK,MAAMA,EAAM,WAAW,KAAK,IACvD3B,IAAOZ,EAAWuB,GAAMoB,CAAM,GAC9BC,IAAUhB,EAAQ5B,EAAWY,GAAM,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ;IACzD,IAASiC,GACPjC,EAAK,YAAY,GACjBA,EAAK,SAAS,GACd,KAAK,IAAIW,EAAK,QAAQ,GAAGqB,CAAO,CAClC;IACA;GACF;GACA,SACE;EACJ;EACA,EAAM,eAAe;EACrB,IAAME,IAAU5B,EAAOsB,CAAM;EAG7B,AAFA,EAAa,UAAUM,GACvB5C,EAAc4C,CAAO,GAChBX,EAAUK,GAAQ1C,CAAK,KAAGC,EAASC,EAAWwC,CAAM,CAAC;CAC5D,GAEMO,MAAsB,MAA+C;EACzE,IAAMC,IAAQT,EAAM;EACpB,AACE,CAACtD,KACDsD,EAAM,QAAQ,SACdA,EAAM,UACNA,EAAM,WACNA,EAAM,WACN,CAACU,GAAeD,GAAOT,EAAM,QAAmBA,EAAM,QAAQ,MAGhEA,EAAM,eAAe,IACRA,EAAM,WACftD,IACCiE,GACCjE,GACAS,MAAgBT,EAAM,cAAc,MACpC,EACF,KAAKA,EAAA,CACJ,MAAM,GACXL,EAAQ,EAAK;CACf,GAEMuE,KAAU,IAAI,KAAK,eAAeC,MAAUC,IAAU;EAC1D,MAAM;EACN,OAAO;CACT,CAAC,CAAC,CAAC,OAAO3B,CAAK,GAET4B,KAAexE,KAASP;CAE9B,OAEE,kBAAC,OAAD;EACE,GAAIgF,GAAmBlG,EAAI;EAC3B,GAAImG,EAAM,eAAe,QAAQ;GAC/B,OAAO7E,KAAQ,CAACf,KAAY,CAACC,IAAW,SAAS;GACjD;GACA,UAAUA;GACV;GACA;EACF,CAAC;EACD,KAAKuB;EACL,WAAWqE,EAAGnH,EAAO,YAAYoH,EAAS;EACnC;EACP,UAAU,MAAM;GACd,AAAI,EAAE,WAAWzE,KAAOuC,GAAO;EACjC;EAdF,UAAA,CAgBE,kBAACmC,GAAmB,UAApB;GAA6B,OAAO;GAClC,UAAA,kBAACC,IAAD;IACE,KAAKvE;IACL,OAAOiE;IACP,aAAaO,MAAe3F,EAAE,wBAAwB;IACtD,IAAIR,EAAW;IACf,cAAYM;IACZ,mBAAiBG;IACjB,oBAAkBT,EAAW;IAC7B,gBAAcK,KAAW,KAAA;IACzB,iBAAeF,KAAY,KAAA;IACjB;IACA;IACV,WAAW,MAAMmD,GAAkB,EAAE,OAAO,KAAK;IACjD,QAAQG;IACR,YAAY,MAAM;KAChB,AAAI,EAAE,QAAQ,gBACd,EAAE,eAAe,GACZxC,IAOHa,EAAS,SACL,cAA2B,qCAAiC,CAAC,EAC7D,MAAM,KARVqB,GAAmBtC,CAAO,GAE1B2B,EADoB3B,KAAW0D,CACN,GACzB7B,GAAoB,EAAI,GACxBxB,EAAQ,EAAI;IAMhB;IACM;IACI;IACJ;IACN,QACEkF,KAAavF,KAAW,CAACX,KAAY,CAACC,IACpC,kBAACtB,IAAD;KACE,MAAM,kBAACwH,IAAD;MAAO,eAAA;MAAY,WAAW;KAAQ,CAAA;KAC5C,MAAK;KACL,cAAY7F,EAAE,kBAAkB;KAChC,SAASmD;KACT,WAAW/E,EAAO;IACnB,CAAA,IAED,kBAAC,QAAD;KACE,WAAWA,EAAO;KAClB,eAAY;KACZ,GAAIkH,EAAM,eAAe,MAAM;KAE/B,UAAA,kBAACQ,GAAD,CAAe,CAAA;IACX,CAAA;GAGX,CAAA;EAC0B,CAAA,GAC7B,kBAACC,IAAD;GACE,KAAKzE;GACL,MAAMb,KAAQ,CAACf,KAAY,CAACC;GAC5B,QAAQoB;GACR,WAAU;GACV,gBAAgB,CAACE,EAAK;GACtB,iBAAiBP,EAAQ,EAAK;GAC9B,2BAA2BK;GAC3B,WAAA;GACA,MAAK;GACL,UAAU;GACV,cAAYjB;GACZ,mBAAiBG;GACjB,WAAW7B,EAAO;GAClB,WAAWyG;GACX,GAAIS,EAAM,eAAe,WAAW,EAAE,OAAO,OAAO,CAAC;GAErD,UAAA,kBAAC,OAAD;IAAK,WAAWlH,EAAO;IAAvB,UAAA;KACE,kBAAC,OAAD;MAAK,WAAWA,EAAO;MAAvB,UAAA,CACE,kBAAC,MAAD;OAAI,IAAIgB;OAAW,WAAWhB,EAAO;OAAS,aAAU;OACrD,UAAA6G;MACC,CAAA,GACJ,kBAAC,OAAD;OAAK,WAAW7G,EAAO;OAAvB,UAAA,CACE,kBAAC,UAAD;QACE,MAAK;QACL,WAAWA,EAAO;QAClB,cAAY4B,EAAE,6BAA6B;QAC3C,eAAe6B,EAASC,EAAWF,GAAO,EAAE,CAAC;QAE7C,UAAA,kBAACoE,GAAD;SAAiB,eAAA;SAAY,WAAW;QAAQ,CAAA;OAC1C,CAAA,GACR,kBAAC,UAAD;QACE,MAAK;QACL,WAAW5H,EAAO;QAClB,cAAY4B,EAAE,yBAAyB;QACvC,eAAe6B,EAASC,EAAWF,GAAO,CAAC,CAAC;QAE5C,UAAA,kBAACqE,IAAD;SAAkB,eAAA;SAAY,WAAW;QAAQ,CAAA;OAC3C,CAAA,CACL;MACF,CAAA,CAAA;;KACL,kBAAC,OAAD;MAAK,MAAK;MAAO,mBAAiB7G;MAAW,WAAWhB,EAAO;MAA/D,UAAA,CACE,kBAAC,OAAD;OAAK,MAAK;OAAM,WAAWA,EAAO;OAC/B,UAAAM,GAAS,KAAK,MACb,kBAAC,OAAD;QAAK,MAAK;QAAyB,WAAWN,EAAO;QAClD,UAAA4B,EAAE,0BAA0BkG,GAAK;OAC/B,GAFyBA,CAEzB,CACN;MACE,CAAA,GACJ,MAAM,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,MAC7B,kBAAC,OAAD;OAAK,MAAK;OAAM,WAAW9H,EAAO;OAC/B,UAAAuF,GAAK,MAAMwC,IAAO,GAAGA,IAAO,IAAI,CAAC,CAAC,CAAC,KAAK,MAAS;QAChD,IAAM5D,IAAMS,EAAOK,CAAI,GACjB+C,IAAW/F,MAAYkC,GACvB8D,IAAU,CAACpC,EAAUZ,GAAMzB,CAAK,GAChC0E,IAAU/D,MAAQwB,GAClBwC,IAAclE,EAAcE,CAAG;QACrC,OACE,kBAAC,OAAD;SACE,MAAK;SAEL,WAAWnE,EAAO;SAClB,MAAM,MAAY;UAChB,AAAIoI,KACFrE,EAAM,QAAQ,IAAII,GAAKiE,CAAO,IAE3BvE,MAAoBM,MAAQyB,KAC7B5B,EAAa,YAAYG,OAEzB,EAAa,UAAU,MACvBiE,EAAQ,MAAM,MAGhBrE,EAAM,QAAQ,OAAOI,CAAG;SAE5B;SACA,aAAWA;SACX,gBAAc8D,IAAU,KAAK,KAAA;SAC7B,cAAY9D;SACZ,iBAAe6D;SACf,gBAAcE,IAAU,SAAS,KAAA;SACjC,iBAAeC,KAAe,KAAA;SAC9B,UAAU,CAACA,KAAehE,MAAQyB,IAAY,IAAI;SAClD,eAAehC,EAAcO,CAAG;SAChC,eAAea,EAAWC,CAAI;SAC9B,YAAY,MAAUe,GAAiBC,GAAOhB,CAAI;SAEjD,UAAAA,EAAK,QAAQ;QACX,GA5BEd,CA4BF;OAET,CAAC;MACE,GAzCwC4D,CAyCxC,CACN,CACE;;KACL,kBAAC,OAAD;MAAK,WAAW/H,EAAO;MAAvB,UAAA,CACE,kBAAC,UAAD;OACE,MAAK;OACL,WAAWA,EAAO;OAClB,UAAUiE,EAAc0B,CAAQ;OAChC,eAAeX,EAAWU,CAAK;OAE9B,UAAA9D,EAAE,kBAAkB;MACf,CAAA,GACP4F,KAAavF,KACZ,kBAAC,UAAD;OACE,MAAK;OACL,WAAWjC,EAAO;OAClB,eAAe;QAEb,AADA+E,GAAY,GACZzC,EAAQ,EAAK;OACf;OAEC,UAAAV,EAAE,kBAAkB;MACf,CAAA,CAEP;;IACF;;EACQ,CAAA,CACZ;;AAET,GAGAyG,IAAehI,EAAM,KAAKE,CAAU"}
|
|
1
|
+
{"version":3,"file":"DatePicker.js","names":["styles","IconButton","useI18n","IconButton_default","datePicker_module_default","React","WEEKDAYS","DatePicker","ariaLabel","ariaLabelledBy","ariaDescribedBy","requiredProp","readOnlyProp","invalidProp","disabledProp","rest","headingId","useId","fc","useFormControlContext","fieldProps","useFormControlProps","disabled","readOnly","required","invalid","accessibleName","label","t","labelledBy","warnControlledProps","value","onChange","current","setCurrent","useControllableState","defaultValue","open","setOpen","onOpenChange","draft","setDraft","useState","input","setInput","field","setField","setInputRef","useMergedRefs","ref","panelRef","useRef","tabContainer","useLayerParent","initialDate","parseDayKey","month","setMonth","monthStart","focusedKey","setFocusedKey","focusPanelOnOpen","setFocusPanelOnOpen","cells","pendingFocus","isDayDisabled","minDate","key","maxDate","commit","next","syncMonthFromValue","parsed","val","handleInputChange","text","dayKey","handleInputBlur","trimmed","handleClear","selectDate","date","toggle","prev","first","start","addDays","days","index","visibleKeys","today","todayKey","activeKey","sameMonth","monthKey","cell","handleDayKeyDown","event","target","weekday","logicalArrowKey","offset","lastDay","localDate","nextKey","handlePanelKeyDown","panel","tabLeavesPanel","adjacentTabbable","heading","locale","language","displayValue","pickDataAttributes","hooks","cn","className","FormControlContext","Input","placeholder","clearable","IconX","IconCalendar","FloatingPanel","IconChevronLeft","IconChevronRight","day","week","selected","outside","isToday","dayDisabled","element","DatePicker_default"],"sources":["../../../../../react/src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from \"react\";\nimport {\n addDays,\n dayKey,\n localDate,\n monthStart,\n parseDayKey,\n sameMonth,\n} from \"@minerva/core\";\nimport { cn } from \"../../utils/cn\";\nimport {\n IconCalendar,\n IconChevronLeft,\n IconChevronRight,\n IconX,\n} from \"../../internal/icons\";\nimport { Input } from \"../Input\";\nimport { IconButton } from \"../IconButton\";\nimport { FloatingPanel } from \"../../internal/FloatingPanel\";\nimport { useLayerParent } from \"../../internal/useDismissableLayer\";\nimport { adjacentTabbable, tabLeavesPanel } from \"../../internal/tabbing\";\nimport { useControllableState } from \"../../internal/useControllableState\";\nimport { warnControlledProps } from \"../../internal/devWarnings\";\nimport { useMergedRefs } from \"../../internal/mergeRefs\";\nimport useI18n from \"../../hooks/useI18n\";\nimport { pickDataAttributes } from \"../../internal/dataAttributes\";\nimport { logicalArrowKey } from \"../../internal/direction\";\nimport {\n FormControlContext,\n useFormControlContext,\n useFormControlProps,\n} from \"../FormControl/context\";\nimport type { DatePickerProps } from \"./types\";\nimport { hooks } from \"../../internal/stylingHooks\";\nimport styles from \"./datePicker.module.scss\";\n\nconst WEEKDAYS = [\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"] as const;\n\n/**\n * DatePicker: type a `\"YYYY-MM-DD\"` date or pick a day from a popup month\n * calendar grid. Works controlled (`value` + `onChange`) or uncontrolled\n * (`defaultValue`). Inside a FormControl the input picks up the field's id,\n * label, description, invalid, required, disabled and read-only state\n * (explicit props win).\n */\nconst DatePicker = ({\n ref,\n value,\n defaultValue,\n onChange,\n placeholder,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n id,\n required: requiredProp,\n readOnly: readOnlyProp,\n invalid: invalidProp,\n name = \"date-picker\",\n disabled: disabledProp,\n clearable = true,\n size = \"medium\",\n minDate,\n maxDate,\n locale,\n className = \"\",\n style,\n onOpenChange,\n ...rest\n}: DatePickerProps) => {\n const { t, language } = useI18n();\n const headingId = useId();\n const fc = useFormControlContext();\n const fieldProps = useFormControlProps({\n id,\n \"aria-describedby\": ariaDescribedBy,\n });\n const disabled = disabledProp ?? fc?.disabled ?? false;\n const readOnly = readOnlyProp ?? fc?.readOnly ?? false;\n const required = requiredProp ?? fc?.required ?? false;\n const invalid = invalidProp ?? fc?.invalid ?? false;\n const accessibleName = label ?? ariaLabel ?? t(\"datePicker.label\");\n const labelledBy =\n ariaLabelledBy ?? (fc && !label && !ariaLabel ? fc.labelId : undefined);\n\n if (process.env.NODE_ENV !== \"production\") {\n warnControlledProps(\"DatePicker\", {\n prop: \"value\",\n value: value === null ? \"\" : value,\n defaultProp: \"defaultValue\",\n defaultValue,\n handlerProp: \"onChange\",\n handler: onChange,\n locked: disabled || readOnly,\n lockHint: \"set `disabled` / `readOnly`\",\n });\n }\n\n const normalizedValue = value === null ? \"\" : value;\n const [current, setCurrent] = useControllableState<string>({\n value: normalizedValue,\n defaultValue: defaultValue ?? \"\",\n name: \"DatePicker\",\n });\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: onOpenChange,\n name: \"DatePicker\",\n prop: \"open\",\n });\n\n const [draft, setDraft] = useState<string | null>(null);\n const [input, setInput] = useState<HTMLInputElement | null>(null);\n const [field, setField] = useState<HTMLDivElement | null>(null);\n const setInputRef = useMergedRefs<HTMLInputElement>(setInput, ref);\n const panelRef = useRef<HTMLDivElement>(null);\n const tabContainer = useLayerParent();\n\n const initialDate = parseDayKey(current || \"\") ?? new Date();\n const [month, setMonth] = useState<Date>(() => monthStart(initialDate));\n const [focusedKey, setFocusedKey] = useState(\"\");\n const [focusPanelOnOpen, setFocusPanelOnOpen] = useState(false);\n const cells = useRef(new Map<string, HTMLDivElement>());\n const pendingFocus = useRef<string | null>(null);\n\n const isDayDisabled = (key: string) => {\n if (minDate && key < minDate) return true;\n if (maxDate && key > maxDate) return true;\n return false;\n };\n\n const commit = (next: string) => {\n setCurrent(next);\n onChange?.(next);\n };\n\n const syncMonthFromValue = (val: string) => {\n const parsed = parseDayKey(val);\n if (parsed) setMonth(monthStart(parsed));\n };\n\n const handleInputChange = (text: string) => {\n setDraft(text);\n if (text === \"\") {\n commit(\"\");\n return;\n }\n const parsed = parseDayKey(text, true);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key)) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n };\n\n const handleInputBlur = () => {\n if (draft === null) return;\n const trimmed = draft.trim();\n if (trimmed === \"\") {\n if (current) commit(\"\");\n } else {\n const parsed = parseDayKey(trimmed, false);\n if (parsed) {\n const key = dayKey(parsed);\n if (!isDayDisabled(key) && key !== current) {\n commit(key);\n setMonth(monthStart(parsed));\n }\n }\n }\n setDraft(null);\n };\n\n const handleClear = () => {\n setDraft(null);\n commit(\"\");\n input?.focus();\n };\n\n const selectDate = (date: Date) => {\n const key = dayKey(date);\n if (disabled || readOnly || isDayDisabled(key)) return;\n setDraft(null);\n commit(key);\n setMonth(monthStart(date));\n setOpen(false);\n input?.focus();\n };\n\n const toggle = () => {\n if (disabled || readOnly) return;\n setFocusPanelOnOpen(false);\n if (!open) syncMonthFromValue(current);\n setOpen((prev) => !prev);\n };\n\n const first = monthStart(month);\n const start = addDays(first, -((first.getDay() + 6) % 7));\n const days = Array.from({ length: 42 }, (_, index) => addDays(start, index));\n const visibleKeys = days.map(dayKey);\n const today = new Date();\n const todayKey = dayKey(today);\n // Roving Tab stop: never a disabled day while the view has an enabled one\n // (e.g. a month cut by minDate), else the grid has no Tab entry.\n const activeKey = [\n focusedKey,\n current,\n sameMonth(today, month) ? todayKey : \"\",\n dayKey(first),\n ...visibleKeys,\n ].find((key) => key && visibleKeys.includes(key) && !isDayDisabled(key));\n const monthKey = dayKey(first);\n\n useEffect(() => {\n if (!open || disabled || !pendingFocus.current) return;\n const cell = cells.current.get(pendingFocus.current);\n if (cell) {\n pendingFocus.current = null;\n cell.focus();\n }\n }, [open, monthKey, focusedKey, disabled]);\n\n const handleDayKeyDown = (\n event: React.KeyboardEvent<HTMLDivElement>,\n date: Date,\n ) => {\n if (disabled || readOnly) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (!event.repeat) selectDate(date);\n return;\n }\n let target: Date;\n const weekday = (date.getDay() + 6) % 7;\n switch (logicalArrowKey(event.key, event.currentTarget)) {\n case \"ArrowLeft\":\n target = addDays(date, -1);\n break;\n case \"ArrowRight\":\n target = addDays(date, 1);\n break;\n case \"ArrowUp\":\n target = addDays(date, -7);\n break;\n case \"ArrowDown\":\n target = addDays(date, 7);\n break;\n case \"Home\":\n target = addDays(date, -weekday);\n break;\n case \"End\":\n target = addDays(date, 6 - weekday);\n break;\n case \"PageUp\":\n case \"PageDown\": {\n const offset =\n (event.key === \"PageUp\" ? -1 : 1) * (event.shiftKey ? 12 : 1);\n const next = monthStart(date, offset);\n const lastDay = addDays(monthStart(next, 1), -1).getDate();\n target = localDate(\n next.getFullYear(),\n next.getMonth(),\n Math.min(date.getDate(), lastDay),\n );\n break;\n }\n default:\n return;\n }\n event.preventDefault();\n const nextKey = dayKey(target);\n pendingFocus.current = nextKey;\n setFocusedKey(nextKey);\n if (!sameMonth(target, month)) setMonth(monthStart(target));\n };\n\n const handlePanelKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const panel = event.currentTarget;\n if (\n !input ||\n event.key !== \"Tab\" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n !tabLeavesPanel(panel, event.target as Element, event.shiftKey)\n )\n return;\n event.preventDefault();\n const next = event.shiftKey\n ? input\n : (adjacentTabbable(\n input,\n tabContainer ?? input.ownerDocument.body,\n false,\n ) ?? input);\n next.focus();\n setOpen(false);\n };\n\n const heading = new Intl.DateTimeFormat(locale ?? language, {\n year: \"numeric\",\n month: \"long\",\n }).format(first);\n\n const displayValue = draft ?? current;\n\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions\n <div\n {...pickDataAttributes(rest)}\n {...hooks(\"date-picker\", \"root\", {\n state: open && !disabled && !readOnly ? \"open\" : \"closed\",\n disabled,\n readonly: readOnly,\n invalid,\n size,\n })}\n ref={setField}\n className={cn(styles.datePicker, className)}\n style={style}\n onClick={(e) => {\n if (e.target === input) toggle();\n }}\n >\n <FormControlContext.Provider value={null}>\n <Input\n ref={setInputRef}\n value={displayValue}\n placeholder={placeholder ?? t(\"datePicker.placeholder\")}\n id={fieldProps.id}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n aria-describedby={fieldProps[\"aria-describedby\"]}\n aria-invalid={invalid || undefined}\n aria-readonly={readOnly || undefined}\n required={required}\n readOnly={readOnly}\n onChange={(e) => handleInputChange(e.target.value)}\n onBlur={handleInputBlur}\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\") return;\n e.preventDefault();\n if (!open) {\n syncMonthFromValue(current);\n const focusTarget = current || todayKey;\n setFocusedKey(focusTarget);\n setFocusPanelOnOpen(true);\n setOpen(true);\n } else {\n panelRef.current\n ?.querySelector<HTMLElement>('[role=\"gridcell\"][tabindex=\"0\"]')\n ?.focus();\n }\n }}\n name={name}\n disabled={disabled}\n size={size}\n suffix={\n clearable && current && !disabled && !readOnly ? (\n <IconButton\n icon={<IconX aria-hidden focusable={false} />}\n size=\"small\"\n aria-label={t(\"datePicker.clear\")}\n onClick={handleClear}\n className={styles.clearButton}\n />\n ) : (\n <span\n className={styles.calendarIcon}\n aria-hidden=\"true\"\n {...hooks(\"date-picker\", \"icon\")}\n >\n <IconCalendar />\n </span>\n )\n }\n />\n </FormControlContext.Provider>\n <FloatingPanel\n ref={panelRef}\n open={open && !disabled && !readOnly}\n anchor={input}\n placement=\"bottom-start\"\n branches={() => [field]}\n onDismiss={() => setOpen(false)}\n returnFocusOnEscape={() => input}\n focusable\n role=\"dialog\"\n tabIndex={-1}\n aria-label={accessibleName}\n aria-labelledby={labelledBy}\n className={styles.popup}\n onKeyDown={handlePanelKeyDown}\n {...hooks(\"date-picker\", \"content\", { state: \"open\" })}\n >\n <div className={styles.panel}>\n <div className={styles.header}>\n <h2 id={headingId} className={styles.heading} aria-live=\"polite\">\n {heading}\n </h2>\n <div className={styles.navGroup}>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.previousMonth\")}\n onClick={() => setMonth(monthStart(month, -1))}\n >\n <IconChevronLeft aria-hidden focusable={false} />\n </button>\n <button\n type=\"button\"\n className={styles.navButton}\n aria-label={t(\"monthCalendar.nextMonth\")}\n onClick={() => setMonth(monthStart(month, 1))}\n >\n <IconChevronRight aria-hidden focusable={false} />\n </button>\n </div>\n </div>\n <div role=\"grid\" aria-labelledby={headingId} className={styles.grid}>\n <div role=\"row\" className={styles.week}>\n {WEEKDAYS.map((day) => (\n <div role=\"columnheader\" key={day} className={styles.weekday}>\n {t(`monthCalendar.weekdays.${day}`)}\n </div>\n ))}\n </div>\n {Array.from({ length: 6 }, (_, week) => (\n <div role=\"row\" className={styles.week} key={week}>\n {days.slice(week * 7, week * 7 + 7).map((date) => {\n const key = dayKey(date);\n const selected = current === key;\n const outside = !sameMonth(date, month);\n const isToday = key === todayKey;\n const dayDisabled = isDayDisabled(key);\n return (\n <div\n role=\"gridcell\"\n key={key}\n className={styles.day}\n ref={(element) => {\n if (element) {\n cells.current.set(key, element);\n if (\n (focusPanelOnOpen && key === activeKey) ||\n pendingFocus.current === key\n ) {\n pendingFocus.current = null;\n element.focus();\n }\n } else {\n cells.current.delete(key);\n }\n }}\n data-date={key}\n data-outside={outside ? \"\" : undefined}\n aria-label={key}\n aria-selected={selected}\n aria-current={isToday ? \"date\" : undefined}\n aria-disabled={dayDisabled || undefined}\n tabIndex={!dayDisabled && key === activeKey ? 0 : -1}\n onFocus={() => setFocusedKey(key)}\n onClick={() => selectDate(date)}\n onKeyDown={(event) => handleDayKeyDown(event, date)}\n >\n {date.getDate()}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div className={styles.footer}>\n <button\n type=\"button\"\n className={styles.footerButton}\n disabled={isDayDisabled(todayKey)}\n onClick={() => selectDate(today)}\n >\n {t(\"datePicker.today\")}\n </button>\n {clearable && current && (\n <button\n type=\"button\"\n className={styles.footerButton}\n onClick={() => {\n handleClear();\n setOpen(false);\n }}\n >\n {t(\"datePicker.clear\")}\n </button>\n )}\n </div>\n </div>\n </FloatingPanel>\n </div>\n );\n};\n\nexport { DatePicker };\nexport default React.memo(DatePicker);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoComplete.vue.js","names":["_sfc_main","AutoComplete_vue_vue_type_script_setup_true_lang_default","AutoComplete_default"],"sources":["../../../../../vue/src/components/AutoComplete/AutoComplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * AutoComplete: a text input (combobox) that suggests options from a list.\n * Supports grouping, custom rendering (`option` slot) and async loading; the\n * input text is `v-model` (or `defaultValue`). Focus stays in the input\n * (`aria-activedescendant`). For picking several values use `TagInput`.\n */\nimport {\n computed,\n getCurrentInstance,\n h,\n onMounted,\n ref,\n shallowRef,\n useAttrs,\n useId,\n watch,\n type FunctionalComponent,\n type VNodeChild,\n} from \"vue\";\nimport { ESCAPE_CONSUMER_ATTRIBUTE } from \"@minerva/dom\";\nimport styles from \"@react-styles/components/AutoComplete/autoComplete.module.scss\";\nimport FloatingPanel from \"../../internal/FloatingPanel.vue\";\nimport { hooks } from \"../../internal/hooks\";\nimport { useControllable } from \"../../internal/controllable\";\nimport { useFormControlProps } from \"../../internal/form-control\";\nimport { Input } from \"../Input\";\nimport { Empty } from \"../Empty\";\nimport { ProgressIndicator } from \"../ProgressIndicator\";\nimport type { AutoCompleteOption, AutoCompleteProps } from \"./types\";\n\ndefineOptions({ name: \"AutoComplete\", inheritAttrs: false });\n\nconst props = withDefaults(defineProps<AutoCompleteProps>(), {\n name: undefined,\n label: undefined,\n mode: \"basic\",\n modelValue: undefined,\n options: () => [],\n defaultValue: undefined,\n groupBy: undefined,\n loading: false,\n inputProps: undefined,\n emptyProps: undefined,\n dropdownClassName: undefined,\n placement: \"bottom\",\n offset: () => ({ x: 0, y: 4 }),\n animation: true,\n filterOption: undefined,\n sortOption: undefined,\n autoHighlight: false,\n fillOnSelect: true,\n groupMode: \"first\",\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: string];\n /** The input text changed (typing or selecting an option) */\n change: [value: string];\n /** An option was picked (mouse or keyboard) */\n select: [option: AutoCompleteOption];\n /** An option was clicked with the mouse */\n optionClick: [option: AutoCompleteOption];\n /** The dropdown opened or closed */\n dropdownVisibleChange: [visible: boolean];\n /**\n * Enter was pressed while no option is active, with the trimmed text\n * (e.g. to run a search); the dropdown closes\n */\n submit: [value: string];\n}>();\n\nconst slots = defineSlots<{\n /** Custom option content (`mode=\"custom\"`, React `renderOption`) */\n option?: (props: { option: AutoCompleteOption }) => unknown;\n /** Custom content shown when no option matches (React `renderEmpty`) */\n empty?: () => unknown;\n}>();\n\nconst PLACEMENT = {\n top: \"top-start\",\n bottom: \"bottom-start\",\n left: \"left-start\",\n right: \"right-start\",\n} as const;\n\nconst attrs = useAttrs();\nconst instance = getCurrentInstance();\n/** Whether a `submit` listener is bound (React: `onSubmit` is set) */\nconst hasSubmitListener = () => !!instance?.vnode.props?.onSubmit;\nconst inputValue = useControllable<string>(props, \"modelValue\", {\n defaultProp: \"defaultValue\",\n fallback: \"\",\n onChange: (next) => emit(\"change\", next),\n name: \"AutoComplete\",\n});\n\nconst visible = ref(false);\nconst setVisible = (next: boolean) => {\n if (visible.value === next) return;\n visible.value = next;\n emit(\"dropdownVisibleChange\", next);\n};\nconst focusedIndex = ref(-1);\nconst hoveredIndex = ref(-1);\nconst container = shallowRef<HTMLDivElement | null>(null);\nconst input = shallowRef<HTMLInputElement | null>(null);\nconst panel = ref<{ element: HTMLElement | null } | null>(null);\nconst vertical = computed(\n () => props.placement === \"top\" || props.placement === \"bottom\",\n);\n\nconst baseId = useId();\nconst listboxId = `${baseId}-listbox`;\n// IME composition in progress: Enter / arrows belong to the IME.\nlet composing = false;\nconst setComposing = (value: boolean) => {\n composing = value;\n};\n\nconst inputReadOnly = () =>\n (props.inputProps?.readOnly ?? props.inputProps?.readonly) as\n boolean | undefined;\n\n// FormControl wiring (id, disabled / read-only state). The input's own\n// disabled / readOnly props still apply.\nconst field = useFormControlProps(() => ({\n id: props.inputProps?.id as string | undefined,\n disabled: props.inputProps?.disabled as boolean | undefined,\n readOnly: inputReadOnly(),\n}));\nconst inputId = computed(() => field.value.id ?? `${baseId}-input`);\nconst blocked = computed(() => field.value.disabled || field.value.readOnly);\n// A disabled / read-only field never shows (or keeps) the dropdown.\nconst shown = computed(() => visible.value && !blocked.value);\n\nfunction open() {\n if (!blocked.value) setVisible(true);\n}\nfunction close() {\n setVisible(false);\n focusedIndex.value = -1;\n}\n\nconst processedOptions = computed(() => {\n const value = inputValue.value;\n const search = value.toLowerCase();\n const result = props.options.filter((option) =>\n props.filterOption\n ? props.filterOption(value, option)\n : option.label.toLowerCase().includes(search),\n );\n return props.sortOption ? [...result].sort(props.sortOption) : result;\n});\n\n/** Groups in order of first appearance, or runs of adjacent options */\nconst groupedOptions = computed<[string, AutoCompleteOption[]][] | null>(() => {\n const groupBy = props.groupBy;\n if (!groupBy) return null;\n if (props.groupMode === \"adjacent\") {\n const runs: [string, AutoCompleteOption[]][] = [];\n processedOptions.value.forEach((option) => {\n const group = groupBy(option);\n const last = runs[runs.length - 1];\n if (last && last[0] === group) last[1].push(option);\n else runs.push([group, [option]]);\n });\n return runs;\n }\n const groups = new Map<string, AutoCompleteOption[]>();\n processedOptions.value.forEach((option) => {\n const group = groupBy(option);\n const list = groups.get(group);\n if (list) list.push(option);\n else groups.set(group, [option]);\n });\n return Array.from(groups.entries());\n});\n\n/** Options in display order; keyboard / hover indexes refer to this list */\nconst navigableOptions = computed(() =>\n groupedOptions.value\n ? groupedOptions.value.flatMap(([, list]) => list)\n : processedOptions.value,\n);\n\n// With autoHighlight the first enabled option is active until the user\n// moves the highlight.\nconst activeIndex = computed(() =>\n focusedIndex.value >= 0\n ? focusedIndex.value\n : props.autoHighlight && shown.value\n ? navigableOptions.value.findIndex((option) => !option.disabled)\n : -1,\n);\n\nfunction moveFocus(step: 1 | -1) {\n const list = navigableOptions.value;\n const count = list.length;\n if (count === 0) return;\n // from \"nothing focused\", ArrowDown starts at the first option and\n // ArrowUp at the last one\n let index =\n activeIndex.value >= 0 ? activeIndex.value : step === 1 ? -1 : count;\n for (let i = 0; i < count; i += 1) {\n index = (index + step + count) % count;\n if (!list[index].disabled) {\n focusedIndex.value = index;\n return;\n }\n }\n}\n\nfunction handleOptionSelect(option: AutoCompleteOption) {\n if (option.disabled) return;\n if (props.fillOnSelect) inputValue.value = option.label;\n close();\n emit(\"select\", option);\n}\n\nfunction handleKeyDown(event: KeyboardEvent) {\n if (\n blocked.value ||\n composing ||\n event.isComposing ||\n event.keyCode === 229\n ) {\n return;\n }\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!visible.value) open();\n moveFocus(1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!visible.value) open();\n moveFocus(-1);\n break;\n case \"Enter\": {\n const option = shown.value\n ? navigableOptions.value[activeIndex.value]\n : undefined;\n const text = inputValue.value.trim();\n if (option) {\n event.preventDefault();\n handleOptionSelect(option);\n } else if (hasSubmitListener() && text) {\n // No active option: submit the typed text (e.g. a search).\n event.preventDefault();\n emit(\"submit\", text);\n close();\n }\n break;\n }\n case \"Escape\":\n // Open: the dropdown's dismissable layer closes it (topmost only).\n // Closed: clears the text (APG combobox), `change(\"\")`.\n if (event !== closingEscape && !shown.value && inputValue.value !== \"\") {\n event.preventDefault();\n inputValue.value = \"\";\n focusedIndex.value = -1;\n }\n break;\n default:\n break;\n }\n}\n\nfunction handleInputChange(next: string) {\n inputValue.value = next;\n focusedIndex.value = -1;\n open();\n}\n\nfunction handleBlur(event: FocusEvent) {\n const next = event.relatedTarget as Node | null;\n const dropdown = panel.value?.element;\n if (next && (dropdown?.contains(next) || container.value?.contains(next))) {\n return;\n }\n close();\n}\n\nfunction handleOptionClick(option: AutoCompleteOption) {\n if (option.disabled || composing) return;\n handleOptionSelect(option);\n emit(\"optionClick\", option);\n input.value?.focus();\n}\n\nfunction onOptionKeyDown(event: KeyboardEvent, option: AutoCompleteOption) {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n handleOptionClick(option);\n}\n\n// Clicking the still-focused input (after a pick or Escape) reopens the\n// dropdown; focus alone does not fire again.\nfunction onInputClick() {\n if (!visible.value) open();\n}\n\nonMounted(() => {\n input.value = container.value?.querySelector(\"input\") ?? null;\n});\n\nconst optionId = (index: number) => `${listboxId}-option-${index}`;\nconst activeOptionId = computed(() =>\n shown.value && activeIndex.value >= 0\n ? optionId(activeIndex.value)\n : undefined,\n);\n\n// Keep the keyboard-focused option scrolled into view\nwatch(\n activeOptionId,\n (id) => {\n if (!id) return;\n const el = container.value?.ownerDocument.getElementById(id);\n el?.scrollIntoView?.({ block: \"nearest\" });\n },\n { flush: \"post\" },\n);\n\n/** Combobox semantics on the inner <input> (after `inputProps`: they win) */\nconst inputBindings = computed(() => ({\n ...props.inputProps,\n id: inputId.value,\n disabled: field.value.disabled,\n readOnly: field.value.readOnly,\n name: props.name,\n modelValue: inputValue.value,\n \"onUpdate:modelValue\": handleInputChange,\n role: \"combobox\",\n \"aria-autocomplete\": \"list\",\n \"aria-expanded\": String(shown.value),\n \"aria-controls\": shown.value ? listboxId : undefined,\n \"aria-activedescendant\": activeOptionId.value,\n // Closed with text: Escape clears it instead of closing an enclosing\n // Modal / Drawer / Popover\n [ESCAPE_CONSUMER_ATTRIBUTE]:\n !shown.value && inputValue.value !== \"\" ? \"\" : undefined,\n}));\n\nconst panelOffset = computed(() => ({\n mainAxis: vertical.value ? props.offset.y : props.offset.x,\n crossAxis: vertical.value ? props.offset.x : props.offset.y,\n}));\n\n/**\n * The Escape that closed the dropdown (the layer handles it before the\n * input's own listener, and Vue state updates synchronously): it must not\n * also clear the text.\n */\nlet closingEscape: KeyboardEvent | null = null;\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n closingEscape = event;\n // Escape during IME composition cancels the composition only\n if (composing || event.isComposing) event.preventDefault();\n}\n\nconst rootAttrs = computed(() => ({\n ...attrs,\n ...hooks(\"autocomplete\", \"root\", {\n state: shown.value ? \"open\" : \"closed\",\n disabled: field.value.disabled,\n readonly: field.value.readOnly,\n loading: props.loading,\n }),\n}));\n\n/** Sections of the list: groups (with a heading unless \"\") or every option */\nconst sections = computed(() => {\n const groups = groupedOptions.value;\n if (!groups) {\n return [\n {\n key: \"all\",\n group: \"\",\n items: processedOptions.value.map((option, index) => ({\n option,\n index,\n })),\n },\n ];\n }\n const order = navigableOptions.value;\n return groups.map(([group, list], groupIndex) => ({\n key: `${groupIndex}-${group}`,\n group,\n items: list.map((option) => ({ option, index: order.indexOf(option) })),\n }));\n});\n\n/** An option of the listbox (`index` in display order) */\nconst OptionRow: FunctionalComponent<{\n option: AutoCompleteOption;\n index: number;\n}> = ({ option, index }) => {\n const active = activeIndex.value === index;\n const highlighted = hoveredIndex.value === index || active;\n const icon = option.icon;\n const content =\n props.mode === \"custom\" && slots.option\n ? slots.option({ option })\n : h(\"div\", { class: styles.basicOption }, [\n icon\n ? h(\n \"span\",\n { class: styles.icon },\n (typeof icon === \"function\"\n ? (icon as () => VNodeChild)()\n : icon) as never,\n )\n : null,\n h(\"div\", { class: styles.content }, [\n h(\"div\", { class: styles.label }, option.label),\n option.description\n ? h(\"div\", { class: styles.description }, option.description)\n : null,\n ]),\n ]);\n return h(\n \"div\",\n {\n class: [\n styles.optionItem,\n option.disabled && styles.disabled,\n option.highlight && styles.highlight,\n highlighted && styles.active,\n ],\n style: option.style,\n role: \"option\",\n // Focus stays in the input (aria-activedescendant); -1 keeps the\n // option out of the tab order while making it programmatically\n // focusable.\n tabindex: -1,\n id: optionId(index),\n \"aria-selected\": active,\n \"aria-disabled\": option.disabled || undefined,\n // keep focus (and the open dropdown) in the input while clicking\n onMousedown: (event: MouseEvent) => event.preventDefault(),\n onClick: () => handleOptionClick(option),\n onKeydown: (event: KeyboardEvent) => onOptionKeyDown(event, option),\n onMouseenter: () => (hoveredIndex.value = index),\n onMouseleave: () => (hoveredIndex.value = -1),\n ...hooks(\"autocomplete\", \"item\", {\n highlighted,\n disabled: option.disabled,\n }),\n },\n content as never,\n );\n};\nOptionRow.props = [\"option\", \"index\"];\n</script>\n\n<template>\n <div\n ref=\"container\"\n :class=\"styles.autoComplete\"\n v-bind=\"rootAttrs\"\n @compositionstart=\"setComposing(true)\"\n @compositionend=\"setComposing(false)\"\n >\n <label\n v-if=\"label\"\n :for=\"inputId\"\n :class=\"styles.label\"\n v-bind=\"hooks('autocomplete', 'label')\"\n >\n {{ label }}\n </label>\n <Input\n v-bind=\"inputBindings\"\n @focus=\"open\"\n @blur=\"handleBlur\"\n @keydown=\"handleKeyDown\"\n @click=\"onInputClick\"\n />\n\n <FloatingPanel\n ref=\"panel\"\n :open=\"shown\"\n :anchor=\"container\"\n :placement=\"PLACEMENT[placement]\"\n :offset=\"panelOffset\"\n match-anchor-width=\"min\"\n :branches=\"() => [container]\"\n :return-focus-on-escape=\"() => input\"\n :class=\"[styles.popup, dropdownClassName]\"\n v-bind=\"hooks('autocomplete', 'content', { state: 'open' })\"\n @escape-key-down=\"onEscapeKeyDown\"\n @dismiss=\"close\"\n >\n <div :class=\"[styles.dropdown, animation && styles.animated]\">\n <!-- While open the listbox always exists (aria-controls target);\n loading / empty states are presentational rows inside it. -->\n <div\n :id=\"listboxId\"\n :class=\"styles.optionList\"\n role=\"listbox\"\n :aria-label=\"label\"\n :aria-busy=\"loading || undefined\"\n v-bind=\"hooks('autocomplete', 'list')\"\n >\n <div\n v-if=\"loading\"\n role=\"presentation\"\n :class=\"styles.loading\"\n v-bind=\"hooks('autocomplete', 'loading')\"\n >\n <ProgressIndicator />\n </div>\n <template v-else-if=\"processedOptions.length > 0\">\n <template v-for=\"section in sections\" :key=\"section.key\">\n <!-- ungrouped options: no heading -->\n <template v-if=\"section.group === ''\">\n <OptionRow\n v-for=\"item in section.items\"\n :key=\"item.option.value\"\n :option=\"item.option\"\n :index=\"item.index\"\n />\n </template>\n <div\n v-else\n :class=\"styles.optionGroup\"\n role=\"group\"\n :aria-label=\"section.group\"\n >\n <div\n :class=\"styles.groupLabel\"\n aria-hidden=\"true\"\n v-bind=\"hooks('autocomplete', 'group-label')\"\n >\n {{ section.group }}\n </div>\n <OptionRow\n v-for=\"item in section.items\"\n :key=\"item.option.value\"\n :option=\"item.option\"\n :index=\"item.index\"\n />\n </div>\n </template>\n </template>\n <div\n v-else\n role=\"presentation\"\n :class=\"styles.empty\"\n v-bind=\"hooks('autocomplete', 'empty')\"\n >\n <slot name=\"empty\"><Empty v-bind=\"emptyProps\" /></slot>\n </div>\n </div>\n </div>\n </FloatingPanel>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"AutoComplete.vue.js","names":["_sfc_main","AutoComplete_vue_vue_type_script_setup_true_lang_default","AutoComplete_default"],"sources":["../../../../../vue/src/components/AutoComplete/AutoComplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * AutoComplete: a text input (combobox) that suggests options from a list.\n * Supports grouping, custom rendering (`option` slot) and async loading; the\n * input text is `v-model` (or `defaultValue`). Focus stays in the input\n * (`aria-activedescendant`). For picking several values use `TagInput`.\n */\nimport {\n computed,\n getCurrentInstance,\n h,\n onMounted,\n ref,\n shallowRef,\n useAttrs,\n useId,\n watch,\n type FunctionalComponent,\n type VNodeChild,\n} from \"vue\";\nimport { ESCAPE_CONSUMER_ATTRIBUTE } from \"@minerva/dom\";\nimport { resolveActiveOptionIndex } from \"@minerva/core\";\nimport styles from \"@react-styles/components/AutoComplete/autoComplete.module.scss\";\nimport FloatingPanel from \"../../internal/FloatingPanel.vue\";\nimport { hooks } from \"../../internal/hooks\";\nimport { useControllable } from \"../../internal/controllable\";\nimport { useFormControlProps } from \"../../internal/form-control\";\nimport { Input } from \"../Input\";\nimport { Empty } from \"../Empty\";\nimport { ProgressIndicator } from \"../ProgressIndicator\";\nimport type { AutoCompleteOption, AutoCompleteProps } from \"./types\";\n\ndefineOptions({ name: \"AutoComplete\", inheritAttrs: false });\n\nconst props = withDefaults(defineProps<AutoCompleteProps>(), {\n name: undefined,\n label: undefined,\n mode: \"basic\",\n modelValue: undefined,\n options: () => [],\n defaultValue: undefined,\n groupBy: undefined,\n loading: false,\n inputProps: undefined,\n emptyProps: undefined,\n dropdownClassName: undefined,\n placement: \"bottom\",\n offset: () => ({ x: 0, y: 4 }),\n animation: true,\n filterOption: undefined,\n sortOption: undefined,\n autoHighlight: false,\n fillOnSelect: true,\n groupMode: \"first\",\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: string];\n /** The input text changed (typing or selecting an option) */\n change: [value: string];\n /** An option was picked (mouse or keyboard) */\n select: [option: AutoCompleteOption];\n /** An option was clicked with the mouse */\n optionClick: [option: AutoCompleteOption];\n /** The dropdown opened or closed */\n dropdownVisibleChange: [visible: boolean];\n /**\n * Enter was pressed while no option is active, with the trimmed text\n * (e.g. to run a search); the dropdown closes\n */\n submit: [value: string];\n}>();\n\nconst slots = defineSlots<{\n /** Custom option content (`mode=\"custom\"`, React `renderOption`) */\n option?: (props: { option: AutoCompleteOption }) => unknown;\n /** Custom content shown when no option matches (React `renderEmpty`) */\n empty?: () => unknown;\n}>();\n\nconst PLACEMENT = {\n top: \"top-start\",\n bottom: \"bottom-start\",\n left: \"left-start\",\n right: \"right-start\",\n} as const;\n\nconst attrs = useAttrs();\nconst instance = getCurrentInstance();\n/** Whether a `submit` listener is bound (React: `onSubmit` is set) */\nconst hasSubmitListener = () => !!instance?.vnode.props?.onSubmit;\nconst inputValue = useControllable<string>(props, \"modelValue\", {\n defaultProp: \"defaultValue\",\n fallback: \"\",\n onChange: (next) => emit(\"change\", next),\n name: \"AutoComplete\",\n});\n\nconst visible = ref(false);\nconst setVisible = (next: boolean) => {\n if (visible.value === next) return;\n visible.value = next;\n emit(\"dropdownVisibleChange\", next);\n};\n// Keyboard highlight, by option identity (survives async option updates)\nconst focusedValue = ref<string | number | null>(null);\nconst hoveredIndex = ref(-1);\nconst container = shallowRef<HTMLDivElement | null>(null);\nconst input = shallowRef<HTMLInputElement | null>(null);\nconst panel = ref<{ element: HTMLElement | null } | null>(null);\nconst vertical = computed(\n () => props.placement === \"top\" || props.placement === \"bottom\",\n);\n\nconst baseId = useId();\nconst listboxId = `${baseId}-listbox`;\n// IME composition in progress: Enter / arrows belong to the IME.\nlet composing = false;\nconst setComposing = (value: boolean) => {\n composing = value;\n};\n\nconst inputReadOnly = () =>\n (props.inputProps?.readOnly ?? props.inputProps?.readonly) as\n boolean | undefined;\n\n// FormControl wiring (id, disabled / read-only state). The input's own\n// disabled / readOnly props still apply.\nconst field = useFormControlProps(() => ({\n id: props.inputProps?.id as string | undefined,\n disabled: props.inputProps?.disabled as boolean | undefined,\n readOnly: inputReadOnly(),\n}));\nconst inputId = computed(() => field.value.id ?? `${baseId}-input`);\nconst blocked = computed(() => field.value.disabled || field.value.readOnly);\n// A disabled / read-only field never shows (or keeps) the dropdown.\nconst shown = computed(() => visible.value && !blocked.value);\n\nfunction open() {\n if (!blocked.value) setVisible(true);\n}\nfunction close() {\n setVisible(false);\n focusedValue.value = null;\n}\n\nconst processedOptions = computed(() => {\n const value = inputValue.value;\n const search = value.toLowerCase();\n const result = props.options.filter((option) =>\n props.filterOption\n ? props.filterOption(value, option)\n : option.label.toLowerCase().includes(search),\n );\n return props.sortOption ? [...result].sort(props.sortOption) : result;\n});\n\n/** Groups in order of first appearance, or runs of adjacent options */\nconst groupedOptions = computed<[string, AutoCompleteOption[]][] | null>(() => {\n const groupBy = props.groupBy;\n if (!groupBy) return null;\n if (props.groupMode === \"adjacent\") {\n const runs: [string, AutoCompleteOption[]][] = [];\n processedOptions.value.forEach((option) => {\n const group = groupBy(option);\n const last = runs[runs.length - 1];\n if (last && last[0] === group) last[1].push(option);\n else runs.push([group, [option]]);\n });\n return runs;\n }\n const groups = new Map<string, AutoCompleteOption[]>();\n processedOptions.value.forEach((option) => {\n const group = groupBy(option);\n const list = groups.get(group);\n if (list) list.push(option);\n else groups.set(group, [option]);\n });\n return Array.from(groups.entries());\n});\n\n/** Options in display order; keyboard / hover indexes refer to this list */\nconst navigableOptions = computed(() =>\n groupedOptions.value\n ? groupedOptions.value.flatMap(([, list]) => list)\n : processedOptions.value,\n);\n\n// Options the keyboard can reach: none while loading (they are hidden).\nconst interactiveOptions = computed(() =>\n props.loading ? [] : navigableOptions.value,\n);\n\n// With autoHighlight the first enabled option is active until the user\n// moves the highlight; a highlight whose option is gone falls back.\nconst activeIndex = computed(() =>\n resolveActiveOptionIndex(\n interactiveOptions.value,\n focusedValue.value,\n props.autoHighlight && shown.value,\n ),\n);\n\nfunction moveFocus(step: 1 | -1) {\n const list = interactiveOptions.value;\n const count = list.length;\n if (count === 0) return;\n // from \"nothing focused\", ArrowDown starts at the first option and\n // ArrowUp at the last one\n let index =\n activeIndex.value >= 0 ? activeIndex.value : step === 1 ? -1 : count;\n for (let i = 0; i < count; i += 1) {\n index = (index + step + count) % count;\n if (!list[index].disabled) {\n focusedValue.value = list[index].value;\n return;\n }\n }\n}\n\nfunction handleOptionSelect(option: AutoCompleteOption) {\n if (option.disabled) return;\n if (props.fillOnSelect) inputValue.value = option.label;\n close();\n emit(\"select\", option);\n}\n\nfunction handleKeyDown(event: KeyboardEvent) {\n if (\n blocked.value ||\n composing ||\n event.isComposing ||\n event.keyCode === 229\n ) {\n return;\n }\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!visible.value) open();\n moveFocus(1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!visible.value) open();\n moveFocus(-1);\n break;\n case \"Enter\": {\n const option = shown.value\n ? interactiveOptions.value[activeIndex.value]\n : undefined;\n const text = inputValue.value.trim();\n if (option) {\n event.preventDefault();\n handleOptionSelect(option);\n } else if (hasSubmitListener() && text) {\n // No active option: submit the typed text (e.g. a search).\n event.preventDefault();\n emit(\"submit\", text);\n close();\n }\n break;\n }\n case \"Escape\":\n // Open: the dropdown's dismissable layer closes it (topmost only).\n // Closed: clears the text (APG combobox), `change(\"\")`.\n if (event !== closingEscape && !shown.value && inputValue.value !== \"\") {\n event.preventDefault();\n inputValue.value = \"\";\n focusedValue.value = null;\n }\n break;\n default:\n break;\n }\n}\n\nfunction handleInputChange(next: string) {\n inputValue.value = next;\n focusedValue.value = null;\n open();\n}\n\nfunction handleBlur(event: FocusEvent) {\n const next = event.relatedTarget as Node | null;\n const dropdown = panel.value?.element;\n if (next && (dropdown?.contains(next) || container.value?.contains(next))) {\n return;\n }\n close();\n}\n\nfunction handleOptionClick(option: AutoCompleteOption) {\n if (option.disabled || composing) return;\n handleOptionSelect(option);\n emit(\"optionClick\", option);\n input.value?.focus();\n}\n\nfunction onOptionKeyDown(event: KeyboardEvent, option: AutoCompleteOption) {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n handleOptionClick(option);\n}\n\n// Clicking the still-focused input (after a pick or Escape) reopens the\n// dropdown; focus alone does not fire again.\nfunction onInputClick() {\n if (!visible.value) open();\n}\n\nonMounted(() => {\n input.value = container.value?.querySelector(\"input\") ?? null;\n});\n\nconst optionId = (index: number) => `${listboxId}-option-${index}`;\nconst activeOptionId = computed(() =>\n shown.value && activeIndex.value >= 0\n ? optionId(activeIndex.value)\n : undefined,\n);\n\n// Keep the keyboard-focused option scrolled into view\nwatch(\n activeOptionId,\n (id) => {\n if (!id) return;\n const el = container.value?.ownerDocument.getElementById(id);\n el?.scrollIntoView?.({ block: \"nearest\" });\n },\n { flush: \"post\" },\n);\n\n/** Combobox semantics on the inner <input> (after `inputProps`: they win) */\nconst inputBindings = computed(() => ({\n ...props.inputProps,\n id: inputId.value,\n disabled: field.value.disabled,\n readOnly: field.value.readOnly,\n name: props.name,\n modelValue: inputValue.value,\n \"onUpdate:modelValue\": handleInputChange,\n role: \"combobox\",\n \"aria-autocomplete\": \"list\",\n \"aria-expanded\": String(shown.value),\n \"aria-controls\": shown.value ? listboxId : undefined,\n \"aria-activedescendant\": activeOptionId.value,\n // Closed with text: Escape clears it instead of closing an enclosing\n // Modal / Drawer / Popover\n [ESCAPE_CONSUMER_ATTRIBUTE]:\n !shown.value && inputValue.value !== \"\" ? \"\" : undefined,\n}));\n\nconst panelOffset = computed(() => ({\n mainAxis: vertical.value ? props.offset.y : props.offset.x,\n crossAxis: vertical.value ? props.offset.x : props.offset.y,\n}));\n\n/**\n * The Escape that closed the dropdown (the layer handles it before the\n * input's own listener, and Vue state updates synchronously): it must not\n * also clear the text.\n */\nlet closingEscape: KeyboardEvent | null = null;\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n closingEscape = event;\n // Escape during IME composition cancels the composition only\n if (composing || event.isComposing) event.preventDefault();\n}\n\nconst rootAttrs = computed(() => ({\n ...attrs,\n ...hooks(\"autocomplete\", \"root\", {\n state: shown.value ? \"open\" : \"closed\",\n disabled: field.value.disabled,\n readonly: field.value.readOnly,\n loading: props.loading,\n }),\n}));\n\n/** Sections of the list: groups (with a heading unless \"\") or every option */\nconst sections = computed(() => {\n const groups = groupedOptions.value;\n if (!groups) {\n return [\n {\n key: \"all\",\n group: \"\",\n items: processedOptions.value.map((option, index) => ({\n option,\n index,\n })),\n },\n ];\n }\n const order = navigableOptions.value;\n return groups.map(([group, list], groupIndex) => ({\n key: `${groupIndex}-${group}`,\n group,\n items: list.map((option) => ({ option, index: order.indexOf(option) })),\n }));\n});\n\n/** An option of the listbox (`index` in display order) */\nconst OptionRow: FunctionalComponent<{\n option: AutoCompleteOption;\n index: number;\n}> = ({ option, index }) => {\n const active = activeIndex.value === index;\n const highlighted = hoveredIndex.value === index || active;\n const icon = option.icon;\n const content =\n props.mode === \"custom\" && slots.option\n ? slots.option({ option })\n : h(\"div\", { class: styles.basicOption }, [\n icon\n ? h(\n \"span\",\n { class: styles.icon },\n (typeof icon === \"function\"\n ? (icon as () => VNodeChild)()\n : icon) as never,\n )\n : null,\n h(\"div\", { class: styles.content }, [\n h(\"div\", { class: styles.label }, option.label),\n option.description\n ? h(\"div\", { class: styles.description }, option.description)\n : null,\n ]),\n ]);\n return h(\n \"div\",\n {\n class: [\n styles.optionItem,\n option.disabled && styles.disabled,\n option.highlight && styles.highlight,\n highlighted && styles.active,\n ],\n style: option.style,\n role: \"option\",\n // Focus stays in the input (aria-activedescendant); -1 keeps the\n // option out of the tab order while making it programmatically\n // focusable.\n tabindex: -1,\n id: optionId(index),\n \"aria-selected\": active,\n \"aria-disabled\": option.disabled || undefined,\n // keep focus (and the open dropdown) in the input while clicking\n onMousedown: (event: MouseEvent) => event.preventDefault(),\n onClick: () => handleOptionClick(option),\n onKeydown: (event: KeyboardEvent) => onOptionKeyDown(event, option),\n onMouseenter: () => (hoveredIndex.value = index),\n onMouseleave: () => (hoveredIndex.value = -1),\n ...hooks(\"autocomplete\", \"item\", {\n highlighted,\n disabled: option.disabled,\n }),\n },\n content as never,\n );\n};\nOptionRow.props = [\"option\", \"index\"];\n</script>\n\n<template>\n <div\n ref=\"container\"\n :class=\"styles.autoComplete\"\n v-bind=\"rootAttrs\"\n @compositionstart=\"setComposing(true)\"\n @compositionend=\"setComposing(false)\"\n >\n <label\n v-if=\"label\"\n :for=\"inputId\"\n :class=\"styles.label\"\n v-bind=\"hooks('autocomplete', 'label')\"\n >\n {{ label }}\n </label>\n <Input\n v-bind=\"inputBindings\"\n @focus=\"open\"\n @blur=\"handleBlur\"\n @keydown=\"handleKeyDown\"\n @click=\"onInputClick\"\n />\n\n <FloatingPanel\n ref=\"panel\"\n :open=\"shown\"\n :anchor=\"container\"\n :placement=\"PLACEMENT[placement]\"\n :offset=\"panelOffset\"\n match-anchor-width=\"min\"\n :branches=\"() => [container]\"\n :return-focus-on-escape=\"() => input\"\n :class=\"[styles.popup, dropdownClassName]\"\n v-bind=\"hooks('autocomplete', 'content', { state: 'open' })\"\n @escape-key-down=\"onEscapeKeyDown\"\n @dismiss=\"close\"\n >\n <div :class=\"[styles.dropdown, animation && styles.animated]\">\n <!-- While open the listbox always exists (aria-controls target);\n loading / empty states are presentational rows inside it. -->\n <div\n :id=\"listboxId\"\n :class=\"styles.optionList\"\n role=\"listbox\"\n :aria-label=\"label\"\n :aria-busy=\"loading || undefined\"\n v-bind=\"hooks('autocomplete', 'list')\"\n >\n <div\n v-if=\"loading\"\n role=\"presentation\"\n :class=\"styles.loading\"\n v-bind=\"hooks('autocomplete', 'loading')\"\n >\n <ProgressIndicator />\n </div>\n <template v-else-if=\"processedOptions.length > 0\">\n <template v-for=\"section in sections\" :key=\"section.key\">\n <!-- ungrouped options: no heading -->\n <template v-if=\"section.group === ''\">\n <OptionRow\n v-for=\"item in section.items\"\n :key=\"item.option.value\"\n :option=\"item.option\"\n :index=\"item.index\"\n />\n </template>\n <div\n v-else\n :class=\"styles.optionGroup\"\n role=\"group\"\n :aria-label=\"section.group\"\n >\n <div\n :class=\"styles.groupLabel\"\n aria-hidden=\"true\"\n v-bind=\"hooks('autocomplete', 'group-label')\"\n >\n {{ section.group }}\n </div>\n <OptionRow\n v-for=\"item in section.items\"\n :key=\"item.option.value\"\n :option=\"item.option\"\n :index=\"item.index\"\n />\n </div>\n </template>\n </template>\n <div\n v-else\n role=\"presentation\"\n :class=\"styles.empty\"\n v-bind=\"hooks('autocomplete', 'empty')\"\n >\n <slot name=\"empty\"><Empty v-bind=\"emptyProps\" /></slot>\n </div>\n </div>\n </div>\n </FloatingPanel>\n </div>\n</template>\n"],"mappings":""}
|