@keboola/design 11.6.0 → 11.6.1
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 +6 -0
- package/dist/{AIKit-BExvt9pt.js → AIKit-CQxVwyAk.js} +7 -7
- package/dist/{AIKit-BExvt9pt.js.map → AIKit-CQxVwyAk.js.map} +1 -1
- package/dist/{Alert-Ba5b2YPq.js → Alert-C4Y9IwMI.js} +2 -2
- package/dist/{Alert-Ba5b2YPq.js.map → Alert-C4Y9IwMI.js.map} +1 -1
- package/dist/{Badge-D0pXdekt.js → Badge-o5jURtpB.js} +2 -2
- package/dist/{Badge-D0pXdekt.js.map → Badge-o5jURtpB.js.map} +1 -1
- package/dist/{BrandEditor-CSANsxUz.js → BrandEditor-CS9P4r2p.js} +5 -5
- package/dist/{BrandEditor-CSANsxUz.js.map → BrandEditor-CS9P4r2p.js.map} +1 -1
- package/dist/{Breadcrumb-g_xn_-Nf.js → Breadcrumb-D1id7YXd.js} +2 -2
- package/dist/{Breadcrumb-g_xn_-Nf.js.map → Breadcrumb-D1id7YXd.js.map} +1 -1
- package/dist/{Checkbox-CUIn2jap.js → Checkbox-Bqr6zXcW.js} +2 -2
- package/dist/{Checkbox-CUIn2jap.js.map → Checkbox-Bqr6zXcW.js.map} +1 -1
- package/dist/{Clipboard-BTW6C-b_.js → Clipboard-C2YBRfD8.js} +2 -2
- package/dist/{Clipboard-BTW6C-b_.js.map → Clipboard-C2YBRfD8.js.map} +1 -1
- package/dist/{ClipboardButton-CwZJdRaz.js → ClipboardButton-CrljClL1.js} +2 -2
- package/dist/{ClipboardButton-CwZJdRaz.js.map → ClipboardButton-CrljClL1.js.map} +1 -1
- package/dist/{CodeEditor-C9zy7PxK.js → CodeEditor-C9AS8Ch0.js} +4 -4
- package/dist/{CodeEditor-C9zy7PxK.js.map → CodeEditor-C9AS8Ch0.js.map} +1 -1
- package/dist/{ColorInput-BZV-u_94.js → ColorInput-Dg87lKcR.js} +2 -2
- package/dist/{ColorInput-BZV-u_94.js.map → ColorInput-Dg87lKcR.js.map} +1 -1
- package/dist/{Combobox-BfIfaVMA.js → Combobox-BfanUAqY.js} +3 -3
- package/dist/{Combobox-BfIfaVMA.js.map → Combobox-BfanUAqY.js.map} +1 -1
- package/dist/{Command-Bfa1kpbt.js → Command-CqxoI_De.js} +2 -2
- package/dist/{Command-Bfa1kpbt.js.map → Command-CqxoI_De.js.map} +1 -1
- package/dist/{CopyField-DpT0Ngz1.js → CopyField-Rx9HPTbJ.js} +2 -2
- package/dist/{CopyField-DpT0Ngz1.js.map → CopyField-Rx9HPTbJ.js.map} +1 -1
- package/dist/{DateInput-DiEd5uCL.js → DateInput-DpifECUQ.js} +2 -2
- package/dist/{DateInput-DiEd5uCL.js.map → DateInput-DpifECUQ.js.map} +1 -1
- package/dist/{DateRangeInput-DPfVYchl.js → DateRangeInput-9MIw7P6L.js} +2 -2
- package/dist/{DateRangeInput-DPfVYchl.js.map → DateRangeInput-9MIw7P6L.js.map} +1 -1
- package/dist/{FieldItem-B7XMmZSz.js → FieldItem-DtPTzNef.js} +3 -3
- package/dist/{FieldItem-B7XMmZSz.js.map → FieldItem-DtPTzNef.js.map} +1 -1
- package/dist/{FileUpload-ABThVZyg.js → FileUpload-DYQCTGjU.js} +3 -3
- package/dist/{FileUpload-ABThVZyg.js.map → FileUpload-DYQCTGjU.js.map} +1 -1
- package/dist/{Form-CsttTHn4.js → Form-DAaatlBk.js} +5 -5
- package/dist/{Form-CsttTHn4.js.map → Form-DAaatlBk.js.map} +1 -1
- package/dist/{FormGroup-DHvTFdno.js → FormGroup-Bl8JmnzJ.js} +3 -3
- package/dist/{FormGroup-DHvTFdno.js.map → FormGroup-Bl8JmnzJ.js.map} +1 -1
- package/dist/{Kbd-Cvvt91Q8.js → Kbd-D1Azcc4g.js} +2 -2
- package/dist/{Kbd-Cvvt91Q8.js.map → Kbd-D1Azcc4g.js.map} +1 -1
- package/dist/{MermaidDiagram-DSI7xMu2.js → MermaidDiagram-CujFxVzk.js} +2 -2
- package/dist/{MermaidDiagram-DSI7xMu2.js.map → MermaidDiagram-CujFxVzk.js.map} +1 -1
- package/dist/{MultiActionButtonGroup-DokHbPgM.js → MultiActionButtonGroup-CNNoBQbv.js} +2 -2
- package/dist/{MultiActionButtonGroup-DokHbPgM.js.map → MultiActionButtonGroup-CNNoBQbv.js.map} +1 -1
- package/dist/{PageToolbar-DExqEYGl.js → PageToolbar-BKVJiDAL.js} +2 -2
- package/dist/{PageToolbar-DExqEYGl.js.map → PageToolbar-BKVJiDAL.js.map} +1 -1
- package/dist/{RadioGroup-DXPbSj8P.js → RadioGroup-CUBsuP7r.js} +2 -2
- package/dist/{RadioGroup-DXPbSj8P.js.map → RadioGroup-CUBsuP7r.js.map} +1 -1
- package/dist/{Search-5uQAiNIP.js → Search-DVpJuzr9.js} +2 -2
- package/dist/{Search-5uQAiNIP.js.map → Search-DVpJuzr9.js.map} +1 -1
- package/dist/{SearchInput-D4UgAXJK.js → SearchInput-Q85p8Ews.js} +2 -2
- package/dist/{SearchInput-D4UgAXJK.js.map → SearchInput-Q85p8Ews.js.map} +1 -1
- package/dist/{SectionNav-OkKCjSA-.js → SectionNav-mpmSM3OC.js} +3 -3
- package/dist/{SectionNav-OkKCjSA-.js.map → SectionNav-mpmSM3OC.js.map} +1 -1
- package/dist/{Sidebar-D3cY1kha.js → Sidebar-CTWsHZhF.js} +2 -2
- package/dist/{Sidebar-D3cY1kha.js.map → Sidebar-CTWsHZhF.js.map} +1 -1
- package/dist/{Slider-CRf-bB4y.js → Slider-Bv0B6lI0.js} +2 -2
- package/dist/{Slider-CRf-bB4y.js.map → Slider-Bv0B6lI0.js.map} +1 -1
- package/dist/{TextInput-DH5SkbsE.js → TextInput-DiEMxVF6.js} +2 -2
- package/dist/{TextInput-DH5SkbsE.js.map → TextInput-DiEMxVF6.js.map} +1 -1
- package/dist/{ThemeProvider-2RMdVGxO.js → ThemeProvider-BI6JWBdJ.js} +2 -2
- package/dist/{ThemeProvider-2RMdVGxO.js.map → ThemeProvider-BI6JWBdJ.js.map} +1 -1
- package/dist/{ZoomableSvg-pooPb1Cu.js → ZoomableSvg-U_VH3QRO.js} +3 -3
- package/dist/{ZoomableSvg-pooPb1Cu.js.map → ZoomableSvg-U_VH3QRO.js.map} +1 -1
- package/dist/editors.js +2 -2
- package/dist/flint.js +1 -1
- package/dist/index.js +30 -30
- package/dist/internal/blocks/AIKit.js +1 -1
- package/dist/internal/blocks/BrandEditor.js +1 -1
- package/dist/internal/blocks/ClipboardButton.js +1 -1
- package/dist/internal/blocks/ColorInput.js +1 -1
- package/dist/internal/blocks/Command.js +1 -1
- package/dist/internal/blocks/CopyField.js +1 -1
- package/dist/internal/blocks/DateInput.js +1 -1
- package/dist/internal/blocks/DateRangeInput.js +1 -1
- package/dist/internal/blocks/ExportMenu.js +1 -1
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
- package/dist/internal/blocks/Form.js +1 -1
- package/dist/internal/blocks/FormGroup.js +1 -1
- package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
- package/dist/internal/blocks/MultiCombobox.js +1 -1
- package/dist/internal/blocks/PageToolbar.js +1 -1
- package/dist/internal/blocks/PasswordInput.js +1 -1
- package/dist/internal/blocks/SearchInput.js +1 -1
- package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
- package/dist/internal/blocks/SectionNav.js +1 -1
- package/dist/internal/blocks/TextInput.js +1 -1
- package/dist/internal/blocks/TimeInput.js +1 -1
- package/dist/internal/components/Alert.js +1 -1
- package/dist/internal/components/Avatar.js +1 -1
- package/dist/internal/components/Badge.js +1 -1
- package/dist/internal/components/Breadcrumb.js +1 -1
- package/dist/internal/components/Checkbox.js +1 -1
- package/dist/internal/components/Clipboard.js +1 -1
- package/dist/internal/components/CollapsiblePanel.js +1 -1
- package/dist/internal/components/Combobox.js +1 -1
- package/dist/internal/components/FileUpload.js +1 -1
- package/dist/internal/components/Kbd.js +1 -1
- package/dist/internal/components/RadioGroup.js +1 -1
- package/dist/internal/components/Search.js +1 -1
- package/dist/internal/components/Sidebar.js +1 -1
- package/dist/internal/components/Slider.js +1 -1
- package/dist/internal/components/ThemeProvider.js +1 -1
- package/dist/internal/components/Tooltip.js +1 -1
- package/dist/internal/components/Truncated.js +1 -1
- package/dist/internal/components/ZoomableSvg.js +1 -1
- package/dist/internal/utils.js +1 -1
- package/dist/markdown-editor.js +4 -4
- package/dist/mermaid.js +1 -1
- package/dist/rjsf.js +9 -9
- package/dist/styles.css +1 -1
- package/dist/testing.js +1 -1
- package/dist/{utils-DSvrhU8E.js → utils-DnkrFYqY.js} +3 -5
- package/dist/utils-DnkrFYqY.js.map +1 -0
- package/package.json +13 -13
- package/dist/utils-DSvrhU8E.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createChangeInputEvent } from "./utils-
|
|
1
|
+
import { createChangeInputEvent } from "./utils-DnkrFYqY.js";
|
|
2
2
|
import { mergeRefs } from "./internal/utils/mergeRefs.js";
|
|
3
3
|
import { Calendar, X } from "./icons-Cek151jC.js";
|
|
4
4
|
import { InputGroup } from "./InputGroup-DcZRlVnN.js";
|
|
@@ -138,4 +138,4 @@ const DateInput = ({ ref, state, variant, focusVariant, sizing, className, value
|
|
|
138
138
|
//#endregion
|
|
139
139
|
export { DateInput };
|
|
140
140
|
|
|
141
|
-
//# sourceMappingURL=DateInput-
|
|
141
|
+
//# sourceMappingURL=DateInput-DpifECUQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateInput-DiEd5uCL.js","names":["CalendarIcon"],"sources":["../src/blocks/DateInput/helpers.ts","../src/blocks/DateInput/DateInput.tsx"],"sourcesContent":["export const formatDate = (date: Date | null | undefined, inputValue: string): string => {\n if (!date) {\n return inputValue;\n }\n return date.toLocaleDateString();\n};\n\n// Detect locale day/month/year order once, matching toLocaleDateString() output\nconst datePartOrder = new Intl.DateTimeFormat()\n .formatToParts(new Date(2000, 0, 2))\n .filter(\n (p): p is { type: 'day' | 'month' | 'year'; value: string } =>\n p.type === 'day' || p.type === 'month' || p.type === 'year',\n )\n .map((p) => p.type);\n\nexport const parseDate = (value: string): Date | null => {\n if (!value.trim()) return null;\n\n // Try locale-aware parsing first (matches toLocaleDateString round-trip)\n const nums = value.match(/\\d+/g)?.map(Number);\n if (nums && nums.length >= 3) {\n const parts = Object.fromEntries(datePartOrder.map((type, i) => [type, nums[i]]));\n const year = parts.year;\n const month = parts.month;\n const day = parts.day;\n\n if (\n year != null &&\n month != null &&\n day != null &&\n month >= 1 &&\n month <= 12 &&\n day >= 1 &&\n day <= 31\n ) {\n const date = new Date(year, month - 1, day);\n if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {\n return date;\n }\n }\n }\n\n // Fallback: detect ISO YYYY-MM-DD and construct as local midnight to avoid UTC offset issues\n const isoMatch = value.match(/^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/);\n if (isoMatch) {\n const y = Number(isoMatch[1]);\n const m = Number(isoMatch[2]) - 1;\n const d = Number(isoMatch[3]);\n const date = new Date(y, m, d);\n if (date.getFullYear() === y && date.getMonth() === m && date.getDate() === d) {\n return date;\n }\n return null;\n }\n\n const fallback = new Date(value);\n return isNaN(fallback.getTime()) ? null : fallback;\n};\n","import { useRef, useState } from 'react';\nimport type {\n ChangeEventHandler,\n ComponentProps,\n ComponentRef,\n FocusEventHandler,\n MouseEventHandler,\n} from 'react';\nimport type { Matcher } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDate, parseDate } from './helpers';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: Date | null;\n defaultValue?: Date | null;\n onValueChange?: (value: Date | null) => void;\n onValueBlur?: (value: Date | null) => void;\n allowClear?: boolean;\n disabledDays?: Matcher | Matcher[];\n endMonth?: Date;\n startMonth?: Date;\n };\n\nexport const DateInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n disabledDays,\n endMonth,\n startMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<Date | null>({\n prop: value,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedDate = parseDate(newValue);\n if (parsedDate !== null || !newValue.trim()) {\n onValueChange?.(parsedDate);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n const formatted = formatDate(currentValue, '');\n setInputValue(formatted);\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDate` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `parseDate` in every locale, so\n // round-tripping an untouched value could wrongly null it.\n const text = event.target.value;\n const parsedDate = text === formatDate(currentValue, '') ? currentValue : parseDate(text);\n onValueBlur?.(parsedDate);\n\n setCurrentValue(parsedDate);\n };\n\n const handleDatePickerChange = (newValue?: Date) => {\n const dateValue = newValue ?? null;\n\n setCurrentValue(dateValue);\n onValueChange?.(dateValue);\n\n setHasFocus(false);\n setIsOpen(false);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDate(currentValue, '');\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n disabled={disabledDays}\n endMonth={endMonth}\n mode=\"single\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n selected={currentValue ?? undefined}\n startMonth={startMonth}\n >\n <InputGroup.Button aria-label=\"Select Date\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateInput-DpifECUQ.js","names":["CalendarIcon"],"sources":["../src/blocks/DateInput/helpers.ts","../src/blocks/DateInput/DateInput.tsx"],"sourcesContent":["export const formatDate = (date: Date | null | undefined, inputValue: string): string => {\n if (!date) {\n return inputValue;\n }\n return date.toLocaleDateString();\n};\n\n// Detect locale day/month/year order once, matching toLocaleDateString() output\nconst datePartOrder = new Intl.DateTimeFormat()\n .formatToParts(new Date(2000, 0, 2))\n .filter(\n (p): p is { type: 'day' | 'month' | 'year'; value: string } =>\n p.type === 'day' || p.type === 'month' || p.type === 'year',\n )\n .map((p) => p.type);\n\nexport const parseDate = (value: string): Date | null => {\n if (!value.trim()) return null;\n\n // Try locale-aware parsing first (matches toLocaleDateString round-trip)\n const nums = value.match(/\\d+/g)?.map(Number);\n if (nums && nums.length >= 3) {\n const parts = Object.fromEntries(datePartOrder.map((type, i) => [type, nums[i]]));\n const year = parts.year;\n const month = parts.month;\n const day = parts.day;\n\n if (\n year != null &&\n month != null &&\n day != null &&\n month >= 1 &&\n month <= 12 &&\n day >= 1 &&\n day <= 31\n ) {\n const date = new Date(year, month - 1, day);\n if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {\n return date;\n }\n }\n }\n\n // Fallback: detect ISO YYYY-MM-DD and construct as local midnight to avoid UTC offset issues\n const isoMatch = value.match(/^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/);\n if (isoMatch) {\n const y = Number(isoMatch[1]);\n const m = Number(isoMatch[2]) - 1;\n const d = Number(isoMatch[3]);\n const date = new Date(y, m, d);\n if (date.getFullYear() === y && date.getMonth() === m && date.getDate() === d) {\n return date;\n }\n return null;\n }\n\n const fallback = new Date(value);\n return isNaN(fallback.getTime()) ? null : fallback;\n};\n","import { useRef, useState } from 'react';\nimport type {\n ChangeEventHandler,\n ComponentProps,\n ComponentRef,\n FocusEventHandler,\n MouseEventHandler,\n} from 'react';\nimport type { Matcher } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDate, parseDate } from './helpers';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: Date | null;\n defaultValue?: Date | null;\n onValueChange?: (value: Date | null) => void;\n onValueBlur?: (value: Date | null) => void;\n allowClear?: boolean;\n disabledDays?: Matcher | Matcher[];\n endMonth?: Date;\n startMonth?: Date;\n };\n\nexport const DateInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n disabledDays,\n endMonth,\n startMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<Date | null>({\n prop: value,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedDate = parseDate(newValue);\n if (parsedDate !== null || !newValue.trim()) {\n onValueChange?.(parsedDate);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n const formatted = formatDate(currentValue, '');\n setInputValue(formatted);\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDate` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `parseDate` in every locale, so\n // round-tripping an untouched value could wrongly null it.\n const text = event.target.value;\n const parsedDate = text === formatDate(currentValue, '') ? currentValue : parseDate(text);\n onValueBlur?.(parsedDate);\n\n setCurrentValue(parsedDate);\n };\n\n const handleDatePickerChange = (newValue?: Date) => {\n const dateValue = newValue ?? null;\n\n setCurrentValue(dateValue);\n onValueChange?.(dateValue);\n\n setHasFocus(false);\n setIsOpen(false);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDate(currentValue, '');\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n disabled={disabledDays}\n endMonth={endMonth}\n mode=\"single\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n selected={currentValue ?? undefined}\n startMonth={startMonth}\n >\n <InputGroup.Button aria-label=\"Select Date\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createChangeInputEvent } from "./utils-
|
|
1
|
+
import { createChangeInputEvent } from "./utils-DnkrFYqY.js";
|
|
2
2
|
import { mergeRefs } from "./internal/utils/mergeRefs.js";
|
|
3
3
|
import { Calendar, X } from "./icons-Cek151jC.js";
|
|
4
4
|
import { InputGroup } from "./InputGroup-DcZRlVnN.js";
|
|
@@ -136,4 +136,4 @@ const DateRangeInput = ({ ref, state, variant, focusVariant, sizing, className,
|
|
|
136
136
|
//#endregion
|
|
137
137
|
export { DateRangeInput };
|
|
138
138
|
|
|
139
|
-
//# sourceMappingURL=DateRangeInput-
|
|
139
|
+
//# sourceMappingURL=DateRangeInput-9MIw7P6L.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRangeInput-DPfVYchl.js","names":["CalendarIcon"],"sources":["../src/blocks/DateRangeInput/helpers.ts","../src/blocks/DateRangeInput/DateRangeInput.tsx"],"sourcesContent":["import type { DateRange } from 'react-day-picker';\n\nexport const formatDateRange = (\n range: DateRange | null | undefined,\n inputValue: string,\n): string => {\n if (!range) {\n return inputValue;\n }\n\n const { from, to } = range;\n const fromStr = from?.toLocaleDateString();\n const toStr = to?.toLocaleDateString();\n return `${fromStr} - ${toStr}`;\n};\n\nconst ISO_DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * `new Date('2024-01-15')` is spec'd as UTC midnight, so reading it back with the\n * local getters this component relies on (`getDate`, `toLocaleDateString`) yields\n * the previous day for users west of UTC. Appending a time makes the ISO form\n * parse as local time instead, while keeping `new Date`'s validation — an\n * out-of-range month or day is still `Invalid Date`, whereas building the parts\n * via `new Date(y, m - 1, d)` would silently roll '2024-13-45' over to 2025-02-14.\n *\n * Every other format accepted here ('01/15/2024', 'Jan 15, 2024', '2024/01/15')\n * is already parsed as local time, so only the date-only ISO form is rewritten.\n */\nconst parseLocalDate = (value: string): Date =>\n ISO_DATE_ONLY.test(value) ? new Date(`${value}T00:00:00`) : new Date(value);\n\nexport const parseDateRange = (value: string): DateRange | null => {\n const parts = value.split(' - ');\n if (parts.length !== 2) {\n return null;\n }\n\n const [fromPart, toPart] = parts;\n if (!fromPart || !toPart) {\n return null;\n }\n\n const from = parseLocalDate(fromPart.trim());\n const to = parseLocalDate(toPart.trim());\n\n if (isNaN(from.getTime()) || isNaN(to.getTime())) {\n return null;\n }\n\n return { from, to };\n};\n","import { useRef, useState } from 'react';\nimport type { ChangeEventHandler, ComponentProps, ComponentRef, FocusEventHandler } from 'react';\nimport type { DateRange } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDateRange, parseDateRange } from './helpers';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: DateRange | null;\n defaultValue?: DateRange | null;\n onValueChange?: (value: DateRange | null) => void;\n onValueBlur?: (value: DateRange | null) => void;\n allowClear?: boolean;\n startMonth?: Date;\n endMonth?: Date;\n };\n\nexport const DateRangeInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value: valueProp,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n startMonth,\n endMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date range',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<DateRange | null>({\n prop: valueProp,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedRange = parseDateRange(newValue);\n if (parsedRange !== null || !newValue.trim()) {\n onValueChange?.(parsedRange);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n setInputValue(formatDateRange(currentValue, ''));\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDateRange` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `new Date(...)` in every locale, so\n // round-tripping an untouched value through `parseDateRange` could wrongly null it.\n const text = event.target.value;\n const parsedRange =\n text === formatDateRange(currentValue, '') ? currentValue : parseDateRange(text);\n onValueBlur?.(parsedRange);\n\n setCurrentValue(parsedRange);\n };\n\n const handleDatePickerChange = (newValue: DateRange | undefined) => {\n const rangeValue = newValue ?? null;\n\n setCurrentValue(rangeValue);\n onValueChange?.(rangeValue);\n\n setHasFocus(false);\n };\n\n const handleClear = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue?.from ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDateRange(currentValue, '');\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date range\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n endMonth={endMonth}\n mode=\"range\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n startMonth={startMonth}\n selected={currentValue ?? undefined}\n >\n <InputGroup.Button aria-label=\"Select date range\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateRangeInput-9MIw7P6L.js","names":["CalendarIcon"],"sources":["../src/blocks/DateRangeInput/helpers.ts","../src/blocks/DateRangeInput/DateRangeInput.tsx"],"sourcesContent":["import type { DateRange } from 'react-day-picker';\n\nexport const formatDateRange = (\n range: DateRange | null | undefined,\n inputValue: string,\n): string => {\n if (!range) {\n return inputValue;\n }\n\n const { from, to } = range;\n const fromStr = from?.toLocaleDateString();\n const toStr = to?.toLocaleDateString();\n return `${fromStr} - ${toStr}`;\n};\n\nconst ISO_DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * `new Date('2024-01-15')` is spec'd as UTC midnight, so reading it back with the\n * local getters this component relies on (`getDate`, `toLocaleDateString`) yields\n * the previous day for users west of UTC. Appending a time makes the ISO form\n * parse as local time instead, while keeping `new Date`'s validation — an\n * out-of-range month or day is still `Invalid Date`, whereas building the parts\n * via `new Date(y, m - 1, d)` would silently roll '2024-13-45' over to 2025-02-14.\n *\n * Every other format accepted here ('01/15/2024', 'Jan 15, 2024', '2024/01/15')\n * is already parsed as local time, so only the date-only ISO form is rewritten.\n */\nconst parseLocalDate = (value: string): Date =>\n ISO_DATE_ONLY.test(value) ? new Date(`${value}T00:00:00`) : new Date(value);\n\nexport const parseDateRange = (value: string): DateRange | null => {\n const parts = value.split(' - ');\n if (parts.length !== 2) {\n return null;\n }\n\n const [fromPart, toPart] = parts;\n if (!fromPart || !toPart) {\n return null;\n }\n\n const from = parseLocalDate(fromPart.trim());\n const to = parseLocalDate(toPart.trim());\n\n if (isNaN(from.getTime()) || isNaN(to.getTime())) {\n return null;\n }\n\n return { from, to };\n};\n","import { useRef, useState } from 'react';\nimport type { ChangeEventHandler, ComponentProps, ComponentRef, FocusEventHandler } from 'react';\nimport type { DateRange } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDateRange, parseDateRange } from './helpers';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: DateRange | null;\n defaultValue?: DateRange | null;\n onValueChange?: (value: DateRange | null) => void;\n onValueBlur?: (value: DateRange | null) => void;\n allowClear?: boolean;\n startMonth?: Date;\n endMonth?: Date;\n };\n\nexport const DateRangeInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value: valueProp,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n startMonth,\n endMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date range',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<DateRange | null>({\n prop: valueProp,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedRange = parseDateRange(newValue);\n if (parsedRange !== null || !newValue.trim()) {\n onValueChange?.(parsedRange);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n setInputValue(formatDateRange(currentValue, ''));\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDateRange` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `new Date(...)` in every locale, so\n // round-tripping an untouched value through `parseDateRange` could wrongly null it.\n const text = event.target.value;\n const parsedRange =\n text === formatDateRange(currentValue, '') ? currentValue : parseDateRange(text);\n onValueBlur?.(parsedRange);\n\n setCurrentValue(parsedRange);\n };\n\n const handleDatePickerChange = (newValue: DateRange | undefined) => {\n const rangeValue = newValue ?? null;\n\n setCurrentValue(rangeValue);\n onValueChange?.(rangeValue);\n\n setHasFocus(false);\n };\n\n const handleClear = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue?.from ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDateRange(currentValue, '');\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date range\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n endMonth={endMonth}\n mode=\"range\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n startMonth={startMonth}\n selected={currentValue ?? undefined}\n >\n <InputGroup.Button aria-label=\"Select date range\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Tooltip } from "./utils-
|
|
1
|
+
import { Tooltip } from "./utils-DnkrFYqY.js";
|
|
2
2
|
import { Info } from "./icons-Cek151jC.js";
|
|
3
3
|
import { Label } from "./internal/components/Label.js";
|
|
4
|
-
import { FormGroup } from "./FormGroup-
|
|
4
|
+
import { FormGroup } from "./FormGroup-Bl8JmnzJ.js";
|
|
5
5
|
import { useRef } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { createFormHookContexts, useStore } from "@tanstack/react-form";
|
|
@@ -105,4 +105,4 @@ const FieldItem = ({ label, action, required, requiredMark = "required", labelli
|
|
|
105
105
|
//#endregion
|
|
106
106
|
export { FieldItem, fieldContext, formContext, useFieldContext, useFormContext };
|
|
107
107
|
|
|
108
|
-
//# sourceMappingURL=FieldItem-
|
|
108
|
+
//# sourceMappingURL=FieldItem-DtPTzNef.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldItem-B7XMmZSz.js","names":[],"sources":["../src/blocks/Form/contexts.ts","../src/blocks/Form/connectors/FieldItem.tsx"],"sourcesContent":["import { createFormHookContexts } from '@tanstack/react-form';\n\nexport const { fieldContext, useFieldContext, formContext, useFormContext } =\n createFormHookContexts();\n","import { type ReactNode, useRef } from 'react';\nimport { useStore } from '@tanstack/react-form';\n\nimport { Label } from '../../../components/Label';\nimport { Tooltip } from '../../../components/Tooltip';\nimport { Info } from '../../../icons';\nimport { FormGroup } from '../../FormGroup';\nimport { useFieldContext, useFormContext } from '../contexts';\n\n/**\n * The a11y wiring `FieldItem` derives from the field and hands back to the control — spread it onto\n * whatever element the field renders. Callers never author these attributes themselves.\n */\ntype FieldControlProps = {\n id: string;\n name: string;\n 'aria-required'?: true;\n 'aria-invalid'?: true;\n 'aria-describedby'?: string;\n /** Present only under `labelling: 'aria-labelledby'` — see the prop. */\n 'aria-labelledby'?: string;\n};\n\n/** Which marker sits next to the label. Purely visual — `aria-required` is driven by `required`. */\ntype RequiredMark = 'required' | 'optional' | 'hidden';\n\n/**\n * How the control takes its accessible name from the label.\n *\n * - `'for'` (default) — `<label for>` points at the control's `id`. Correct for the *labelable*\n * elements: `input`, `textarea`, `select`, `button`, and anything rendering one.\n * - `'aria-labelledby'` — the label gets an id and it comes back in `control['aria-labelledby']`,\n * with no `for` emitted. For controls that are **not** labelable elements: a CodeMirror or Lexical\n * editable region, or a composite widget whose focusable node is a `div[role]`. `<label for>`\n * pointing at one of those is invalid HTML and silently names nothing.\n */\ntype Labelling = 'for' | 'aria-labelledby';\n\ntype Props = {\n label?: ReactNode;\n /**\n * Optional node rendered at the trailing edge of the label row (opposite the label) — e.g. a\n * \"Forgot password?\" link beside a Password label. Presentational placement only; it is a sibling\n * of the `<Label>`, not part of the field's accessible name. Provide an interactive element\n * (`ButtonInline` / `Link`).\n */\n action?: ReactNode;\n required?: boolean;\n /**\n * Which marker to show beside the label — gated by `required` so it never lies: `'required'`\n * renders `*` only when the field is `required`; `'optional'` renders `(optional)` only when it\n * is not; `'hidden'` renders neither. Defaults to `'required'`.\n */\n requiredMark?: RequiredMark;\n /** See {@link Labelling}. Defaults to `'for'`. */\n labelling?: Labelling;\n help?: ReactNode;\n tooltip?: ReactNode;\n className?: string;\n 'aria-describedby'?: string;\n children: (control: FieldControlProps) => ReactNode;\n};\n\n/**\n * The frame props a connector re-exposes to its own callers.\n *\n * - `labelling` is not among them: which mechanism names the control follows from what the control\n * *is*, so the connector picks it, not the call site.\n * - Leaving it in would type-check and do nothing — no connector forwards it — and land in the rest\n * spread instead, which for `TextField` / `TextareaField` reaches the DOM `<input>`.\n */\nexport type FieldItemProps = Omit<Props, 'children' | 'labelling'>;\n\n/**\n * Shared frame for a form field: label (+ required marker + tooltip), the control, and help/error\n * text. It reads the field from context and owns everything derivable — validity, the error/help\n * ids, and the control's `aria-*` wiring — so a connector only picks a control and binds its value.\n */\nexport const FieldItem = ({\n label,\n action,\n required,\n requiredMark = 'required',\n labelling = 'for',\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n children,\n}: Props) => {\n const field = useFieldContext();\n const form = useFormContext();\n const { errors, isBlurred } = field.state.meta;\n const submissionAttempts = useStore(form.store, (state) => state.submissionAttempts);\n\n /**\n * The submit count as of this field's first render.\n *\n * - `submissionAttempts` never goes down, so a bare `> 0` would reveal errors on a field that mounted\n * *after* a failed submit — switch a type on a form that already failed Save and every freshly\n * revealed control says \"Required\" before the user reaches it.\n * - Comparing against the mount value asks the question that matters: has a submit happened while this\n * field was on screen?\n * - `form.reset()` puts the counter back to 0 without unmounting anything, so the baseline has to\n * follow it down. Left alone it outruns the counter and the next submit compares `1 > 1` — the\n * error stays hidden until a second one.\n */\n const attemptsAtMountRef = useRef(submissionAttempts);\n if (submissionAttempts < attemptsAtMountRef.current)\n attemptsAtMountRef.current = submissionAttempts;\n\n /**\n * ⚠️ **Blurred, not touched.**\n *\n * `isTouched` looks like the right gate and is not: `FormApi.setFieldValue` sets it, so filling a field\n * *for* the user — an id derived from a name, a default written when a type is picked — reads as the\n * user having been there (`validateField` and `validateAllFields` set it too). The visible result is\n * \"Required\" under a control the user has never been near.\n *\n * `isBlurred` is per-field and only a real blur sets it: the user was in this control and left it.\n * A submit attempt reveals everything that was on screen for it, because a field nobody visited still\n * has to explain itself once the button is pressed. `setServerFieldErrors` marks `isBlurred` for the\n * same reason — a mutation that fails outside a submit has neither signal otherwise.\n */\n const isInvalid =\n (isBlurred || submissionAttempts > attemptsAtMountRef.current) && errors.length > 0;\n\n const errorId = `${field.name}-error`;\n const descriptionId = `${field.name}-description`;\n const labelId = `${field.name}-label`;\n const namesByAria = labelling === 'aria-labelledby';\n // Help and error are not exclusive — link the control to whichever are present. Space-delimited\n // ARIA idref list; falsy entries dropped, and `undefined` when empty so the attr is omitted.\n const describedBy =\n [ariaDescribedBy, !!help && descriptionId, isInvalid && errorId].filter(Boolean).join(' ') ||\n undefined;\n\n return (\n <FormGroup className={className}>\n {(label || action) && (\n <div className=\"tw:flex tw:items-center tw:justify-between tw:gap-2\">\n <div className=\"tw:flex tw:items-center tw:gap-1\">\n {/* Marker binds to the label text; the interactive tooltip button is a sibling. */}\n {label && (\n // `htmlFor` only when the control is a labelable element. Under `aria-labelledby` the\n // label carries an id instead and the control points back at it — a `for` aimed at a\n // `div[role=textbox]` is invalid HTML and names nothing.\n <Label\n htmlFor={namesByAria ? undefined : field.name}\n id={namesByAria ? labelId : undefined}\n >\n {label}\n {/* Marker follows both flags: `*` only when actually required, `(optional)` only\n when not — a mismatched marker would lie. `hidden` shows neither. */}\n {requiredMark === 'required' && required && <Label.Required />}\n {requiredMark === 'optional' && !required && <Label.Optional />}\n </Label>\n )}\n\n {tooltip && (\n <Tooltip tooltip={tooltip} placement=\"top\" triggerAsChild>\n <button\n type=\"button\"\n aria-label={\n typeof label === 'string'\n ? `More information about ${label}`\n : 'More information'\n }\n className=\"tw:text-muted-foreground tw:focus:outline-hidden tw:focus-visible:text-primary tailwindcss-preflight\"\n >\n <Info className=\"tw:size-3\" />\n </button>\n </Tooltip>\n )}\n </div>\n\n {action}\n </div>\n )}\n\n {children({\n id: field.name,\n name: field.name,\n 'aria-required': required || undefined,\n 'aria-invalid': isInvalid || undefined,\n 'aria-describedby': describedBy,\n 'aria-labelledby': namesByAria && label ? labelId : undefined,\n })}\n\n {(help || isInvalid) && (\n <div>\n {help && <FormGroup.Help id={descriptionId}>{help}</FormGroup.Help>}\n {isInvalid && <FormGroup.Error id={errorId} errors={errors} />}\n </div>\n )}\n </FormGroup>\n );\n};\n"],"mappings":";;;;;;;;AAEA,MAAa,EAAE,cAAc,iBAAiB,aAAa,mBACzD,uBAAuB;;;;;;;;AC2EzB,MAAa,aAAa,EACxB,OACA,QACA,UACA,eAAe,YACf,YAAY,OACZ,MACA,SACA,WACA,oBAAoB,iBACpB,eACW;CACX,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,OAAO,eAAe;CAC5B,MAAM,EAAE,QAAQ,cAAc,MAAM,MAAM;CAC1C,MAAM,qBAAqB,SAAS,KAAK,QAAQ,UAAU,MAAM,kBAAkB;;;;;;;;;;;;;CAcnF,MAAM,qBAAqB,OAAO,kBAAkB;CACpD,IAAI,qBAAqB,mBAAmB,SAC1C,mBAAmB,UAAU;;;;;;;;;;;;;;CAe/B,MAAM,aACH,aAAa,qBAAqB,mBAAmB,YAAY,OAAO,SAAS;CAEpF,MAAM,UAAU,GAAG,MAAM,KAAK;CAC9B,MAAM,gBAAgB,GAAG,MAAM,KAAK;CACpC,MAAM,UAAU,GAAG,MAAM,KAAK;CAC9B,MAAM,cAAc,cAAc;CAGlC,MAAM,cACJ;EAAC;EAAiB,CAAC,CAAC,QAAQ;EAAe,aAAa;CAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KACzF,KAAA;CAEF,OACE,qBAAC,WAAD;EAAsB;EAAtB,UAAA;IACI,SAAS,WACT,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CAEG,SAIC,qBAAC,OAAD;MACE,SAAS,cAAc,KAAA,IAAY,MAAM;MACzC,IAAI,cAAc,UAAU,KAAA;MAF9B,UAAA;OAIG;OAGA,iBAAiB,cAAc,YAAY,oBAAC,MAAM,UAAP,CAAiB,CAAA;OAC5D,iBAAiB,cAAc,CAAC,YAAY,oBAAC,MAAM,UAAP,CAAiB,CAAA;MACzD;KAGR,CAAA,GAAA,WACC,oBAAC,SAAD;MAAkB;MAAS,WAAU;MAAM,gBAAA;MACzC,UAAA,oBAAC,UAAD;OACE,MAAK;OACL,cACE,OAAO,UAAU,WACb,0BAA0B,UAC1B;OAEN,WAAU;OAEV,UAAA,oBAAC,MAAD,EAAM,WAAU,YAAa,CAAA;MACvB,CAAA;KACD,CAAA,CAER;IAEJ,CAAA,GAAA,MACE;;GAGN,SAAS;IACR,IAAI,MAAM;IACV,MAAM,MAAM;IACZ,iBAAiB,YAAY,KAAA;IAC7B,gBAAgB,aAAa,KAAA;IAC7B,oBAAoB;IACpB,mBAAmB,eAAe,QAAQ,UAAU,KAAA;GACtD,CAAC;IAEC,QAAQ,cACR,qBAAC,OAAD,EAAA,UAAA,CACG,QAAQ,oBAAC,UAAU,MAAX;IAAgB,IAAI;IAAgB,UAAA;GAAqB,CAAA,GACjE,aAAa,oBAAC,UAAU,OAAX;IAAiB,IAAI;IAAiB;GAAS,CAAA,CAC1D,EAAA,CAAA;EAEE;;AAEf"}
|
|
1
|
+
{"version":3,"file":"FieldItem-DtPTzNef.js","names":[],"sources":["../src/blocks/Form/contexts.ts","../src/blocks/Form/connectors/FieldItem.tsx"],"sourcesContent":["import { createFormHookContexts } from '@tanstack/react-form';\n\nexport const { fieldContext, useFieldContext, formContext, useFormContext } =\n createFormHookContexts();\n","import { type ReactNode, useRef } from 'react';\nimport { useStore } from '@tanstack/react-form';\n\nimport { Label } from '../../../components/Label';\nimport { Tooltip } from '../../../components/Tooltip';\nimport { Info } from '../../../icons';\nimport { FormGroup } from '../../FormGroup';\nimport { useFieldContext, useFormContext } from '../contexts';\n\n/**\n * The a11y wiring `FieldItem` derives from the field and hands back to the control — spread it onto\n * whatever element the field renders. Callers never author these attributes themselves.\n */\ntype FieldControlProps = {\n id: string;\n name: string;\n 'aria-required'?: true;\n 'aria-invalid'?: true;\n 'aria-describedby'?: string;\n /** Present only under `labelling: 'aria-labelledby'` — see the prop. */\n 'aria-labelledby'?: string;\n};\n\n/** Which marker sits next to the label. Purely visual — `aria-required` is driven by `required`. */\ntype RequiredMark = 'required' | 'optional' | 'hidden';\n\n/**\n * How the control takes its accessible name from the label.\n *\n * - `'for'` (default) — `<label for>` points at the control's `id`. Correct for the *labelable*\n * elements: `input`, `textarea`, `select`, `button`, and anything rendering one.\n * - `'aria-labelledby'` — the label gets an id and it comes back in `control['aria-labelledby']`,\n * with no `for` emitted. For controls that are **not** labelable elements: a CodeMirror or Lexical\n * editable region, or a composite widget whose focusable node is a `div[role]`. `<label for>`\n * pointing at one of those is invalid HTML and silently names nothing.\n */\ntype Labelling = 'for' | 'aria-labelledby';\n\ntype Props = {\n label?: ReactNode;\n /**\n * Optional node rendered at the trailing edge of the label row (opposite the label) — e.g. a\n * \"Forgot password?\" link beside a Password label. Presentational placement only; it is a sibling\n * of the `<Label>`, not part of the field's accessible name. Provide an interactive element\n * (`ButtonInline` / `Link`).\n */\n action?: ReactNode;\n required?: boolean;\n /**\n * Which marker to show beside the label — gated by `required` so it never lies: `'required'`\n * renders `*` only when the field is `required`; `'optional'` renders `(optional)` only when it\n * is not; `'hidden'` renders neither. Defaults to `'required'`.\n */\n requiredMark?: RequiredMark;\n /** See {@link Labelling}. Defaults to `'for'`. */\n labelling?: Labelling;\n help?: ReactNode;\n tooltip?: ReactNode;\n className?: string;\n 'aria-describedby'?: string;\n children: (control: FieldControlProps) => ReactNode;\n};\n\n/**\n * The frame props a connector re-exposes to its own callers.\n *\n * - `labelling` is not among them: which mechanism names the control follows from what the control\n * *is*, so the connector picks it, not the call site.\n * - Leaving it in would type-check and do nothing — no connector forwards it — and land in the rest\n * spread instead, which for `TextField` / `TextareaField` reaches the DOM `<input>`.\n */\nexport type FieldItemProps = Omit<Props, 'children' | 'labelling'>;\n\n/**\n * Shared frame for a form field: label (+ required marker + tooltip), the control, and help/error\n * text. It reads the field from context and owns everything derivable — validity, the error/help\n * ids, and the control's `aria-*` wiring — so a connector only picks a control and binds its value.\n */\nexport const FieldItem = ({\n label,\n action,\n required,\n requiredMark = 'required',\n labelling = 'for',\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n children,\n}: Props) => {\n const field = useFieldContext();\n const form = useFormContext();\n const { errors, isBlurred } = field.state.meta;\n const submissionAttempts = useStore(form.store, (state) => state.submissionAttempts);\n\n /**\n * The submit count as of this field's first render.\n *\n * - `submissionAttempts` never goes down, so a bare `> 0` would reveal errors on a field that mounted\n * *after* a failed submit — switch a type on a form that already failed Save and every freshly\n * revealed control says \"Required\" before the user reaches it.\n * - Comparing against the mount value asks the question that matters: has a submit happened while this\n * field was on screen?\n * - `form.reset()` puts the counter back to 0 without unmounting anything, so the baseline has to\n * follow it down. Left alone it outruns the counter and the next submit compares `1 > 1` — the\n * error stays hidden until a second one.\n */\n const attemptsAtMountRef = useRef(submissionAttempts);\n if (submissionAttempts < attemptsAtMountRef.current)\n attemptsAtMountRef.current = submissionAttempts;\n\n /**\n * ⚠️ **Blurred, not touched.**\n *\n * `isTouched` looks like the right gate and is not: `FormApi.setFieldValue` sets it, so filling a field\n * *for* the user — an id derived from a name, a default written when a type is picked — reads as the\n * user having been there (`validateField` and `validateAllFields` set it too). The visible result is\n * \"Required\" under a control the user has never been near.\n *\n * `isBlurred` is per-field and only a real blur sets it: the user was in this control and left it.\n * A submit attempt reveals everything that was on screen for it, because a field nobody visited still\n * has to explain itself once the button is pressed. `setServerFieldErrors` marks `isBlurred` for the\n * same reason — a mutation that fails outside a submit has neither signal otherwise.\n */\n const isInvalid =\n (isBlurred || submissionAttempts > attemptsAtMountRef.current) && errors.length > 0;\n\n const errorId = `${field.name}-error`;\n const descriptionId = `${field.name}-description`;\n const labelId = `${field.name}-label`;\n const namesByAria = labelling === 'aria-labelledby';\n // Help and error are not exclusive — link the control to whichever are present. Space-delimited\n // ARIA idref list; falsy entries dropped, and `undefined` when empty so the attr is omitted.\n const describedBy =\n [ariaDescribedBy, !!help && descriptionId, isInvalid && errorId].filter(Boolean).join(' ') ||\n undefined;\n\n return (\n <FormGroup className={className}>\n {(label || action) && (\n <div className=\"tw:flex tw:items-center tw:justify-between tw:gap-2\">\n <div className=\"tw:flex tw:items-center tw:gap-1\">\n {/* Marker binds to the label text; the interactive tooltip button is a sibling. */}\n {label && (\n // `htmlFor` only when the control is a labelable element. Under `aria-labelledby` the\n // label carries an id instead and the control points back at it — a `for` aimed at a\n // `div[role=textbox]` is invalid HTML and names nothing.\n <Label\n htmlFor={namesByAria ? undefined : field.name}\n id={namesByAria ? labelId : undefined}\n >\n {label}\n {/* Marker follows both flags: `*` only when actually required, `(optional)` only\n when not — a mismatched marker would lie. `hidden` shows neither. */}\n {requiredMark === 'required' && required && <Label.Required />}\n {requiredMark === 'optional' && !required && <Label.Optional />}\n </Label>\n )}\n\n {tooltip && (\n <Tooltip tooltip={tooltip} placement=\"top\" triggerAsChild>\n <button\n type=\"button\"\n aria-label={\n typeof label === 'string'\n ? `More information about ${label}`\n : 'More information'\n }\n className=\"tw:text-muted-foreground tw:focus:outline-hidden tw:focus-visible:text-primary tailwindcss-preflight\"\n >\n <Info className=\"tw:size-3\" />\n </button>\n </Tooltip>\n )}\n </div>\n\n {action}\n </div>\n )}\n\n {children({\n id: field.name,\n name: field.name,\n 'aria-required': required || undefined,\n 'aria-invalid': isInvalid || undefined,\n 'aria-describedby': describedBy,\n 'aria-labelledby': namesByAria && label ? labelId : undefined,\n })}\n\n {(help || isInvalid) && (\n <div>\n {help && <FormGroup.Help id={descriptionId}>{help}</FormGroup.Help>}\n {isInvalid && <FormGroup.Error id={errorId} errors={errors} />}\n </div>\n )}\n </FormGroup>\n );\n};\n"],"mappings":";;;;;;;;AAEA,MAAa,EAAE,cAAc,iBAAiB,aAAa,mBACzD,uBAAuB;;;;;;;;AC2EzB,MAAa,aAAa,EACxB,OACA,QACA,UACA,eAAe,YACf,YAAY,OACZ,MACA,SACA,WACA,oBAAoB,iBACpB,eACW;CACX,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,OAAO,eAAe;CAC5B,MAAM,EAAE,QAAQ,cAAc,MAAM,MAAM;CAC1C,MAAM,qBAAqB,SAAS,KAAK,QAAQ,UAAU,MAAM,kBAAkB;;;;;;;;;;;;;CAcnF,MAAM,qBAAqB,OAAO,kBAAkB;CACpD,IAAI,qBAAqB,mBAAmB,SAC1C,mBAAmB,UAAU;;;;;;;;;;;;;;CAe/B,MAAM,aACH,aAAa,qBAAqB,mBAAmB,YAAY,OAAO,SAAS;CAEpF,MAAM,UAAU,GAAG,MAAM,KAAK;CAC9B,MAAM,gBAAgB,GAAG,MAAM,KAAK;CACpC,MAAM,UAAU,GAAG,MAAM,KAAK;CAC9B,MAAM,cAAc,cAAc;CAGlC,MAAM,cACJ;EAAC;EAAiB,CAAC,CAAC,QAAQ;EAAe,aAAa;CAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KACzF,KAAA;CAEF,OACE,qBAAC,WAAD;EAAsB;EAAtB,UAAA;IACI,SAAS,WACT,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CAEG,SAIC,qBAAC,OAAD;MACE,SAAS,cAAc,KAAA,IAAY,MAAM;MACzC,IAAI,cAAc,UAAU,KAAA;MAF9B,UAAA;OAIG;OAGA,iBAAiB,cAAc,YAAY,oBAAC,MAAM,UAAP,CAAiB,CAAA;OAC5D,iBAAiB,cAAc,CAAC,YAAY,oBAAC,MAAM,UAAP,CAAiB,CAAA;MACzD;KAGR,CAAA,GAAA,WACC,oBAAC,SAAD;MAAkB;MAAS,WAAU;MAAM,gBAAA;MACzC,UAAA,oBAAC,UAAD;OACE,MAAK;OACL,cACE,OAAO,UAAU,WACb,0BAA0B,UAC1B;OAEN,WAAU;OAEV,UAAA,oBAAC,MAAD,EAAM,WAAU,YAAa,CAAA;MACvB,CAAA;KACD,CAAA,CAER;IAEJ,CAAA,GAAA,MACE;;GAGN,SAAS;IACR,IAAI,MAAM;IACV,MAAM,MAAM;IACZ,iBAAiB,YAAY,KAAA;IAC7B,gBAAgB,aAAa,KAAA;IAC7B,oBAAoB;IACpB,mBAAmB,eAAe,QAAQ,UAAU,KAAA;GACtD,CAAC;IAEC,QAAQ,cACR,qBAAC,OAAD,EAAA,UAAA,CACG,QAAQ,oBAAC,UAAU,MAAX;IAAgB,IAAI;IAAgB,UAAA;GAAqB,CAAA,GACjE,aAAa,oBAAC,UAAU,OAAX;IAAiB,IAAI;IAAiB;GAAS,CAAA,CAC1D,EAAA,CAAA;EAEE;;AAEf"}
|
|
@@ -1711,8 +1711,8 @@ function _objectWithoutPropertiesLoose(source, excluded) {
|
|
|
1711
1711
|
if (source == null) return {};
|
|
1712
1712
|
var target = {};
|
|
1713
1713
|
var sourceKeys = Object.keys(source);
|
|
1714
|
-
var key, i;
|
|
1715
|
-
for (
|
|
1714
|
+
var key, i = 0;
|
|
1715
|
+
for (; i < sourceKeys.length; i++) {
|
|
1716
1716
|
key = sourceKeys[i];
|
|
1717
1717
|
if (excluded.indexOf(key) >= 0) continue;
|
|
1718
1718
|
target[key] = source[key];
|
|
@@ -2524,4 +2524,4 @@ const FileUpload = Object.assign(FileUploadInner, {
|
|
|
2524
2524
|
//#endregion
|
|
2525
2525
|
export { FileUpload, useFileDropTarget, useFileUploadRejections };
|
|
2526
2526
|
|
|
2527
|
-
//# sourceMappingURL=FileUpload-
|
|
2527
|
+
//# sourceMappingURL=FileUpload-DYQCTGjU.js.map
|