@fremtind/jokul 4.5.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/build-stats.html +1 -1
- package/build/cjs/components/datepicker/DatePicker.cjs +1 -1
- package/build/cjs/components/datepicker/DatePicker.cjs.map +1 -1
- package/build/cjs/components/icon/Icon.cjs +1 -1
- package/build/cjs/components/icon/Icon.cjs.map +1 -1
- package/build/cjs/components/icon/Icon.d.cts +2 -2
- package/build/cjs/components/icon/icons/GreenCheckIcon.cjs +1 -1
- package/build/cjs/components/icon/icons/GreenCheckIcon.cjs.map +1 -1
- package/build/cjs/components/icon/icons/GreenCheckIcon.d.cts +2 -3
- package/build/cjs/components/icon/icons/RedCrossIcon.cjs +1 -1
- package/build/cjs/components/icon/icons/RedCrossIcon.cjs.map +1 -1
- package/build/cjs/components/icon/icons/RedCrossIcon.d.cts +2 -3
- package/build/cjs/components/number-input/NumberInput.cjs +2 -0
- package/build/cjs/components/number-input/NumberInput.cjs.map +1 -0
- package/build/cjs/components/number-input/NumberInput.d.cts +7 -0
- package/build/cjs/components/number-input/index.cjs +2 -0
- package/build/cjs/components/number-input/index.cjs.map +1 -0
- package/build/cjs/components/number-input/index.d.cts +2 -0
- package/build/cjs/components/number-input/types.cjs +2 -0
- package/build/cjs/components/number-input/types.cjs.map +1 -0
- package/build/cjs/components/number-input/types.d.cts +20 -0
- package/build/cjs/components/text-area/BaseTextArea.cjs +1 -1
- package/build/cjs/components/text-area/BaseTextArea.cjs.map +1 -1
- package/build/cjs/components/text-area/counter.cjs +2 -0
- package/build/cjs/components/text-area/counter.cjs.map +1 -0
- package/build/cjs/components/text-area/counter.d.cts +2 -0
- package/build/cjs/components/text-area/types.d.cts +21 -1
- package/build/es/components/datepicker/DatePicker.js +1 -1
- package/build/es/components/datepicker/DatePicker.js.map +1 -1
- package/build/es/components/icon/Icon.d.ts +2 -2
- package/build/es/components/icon/Icon.js +1 -1
- package/build/es/components/icon/Icon.js.map +1 -1
- package/build/es/components/icon/icons/GreenCheckIcon.d.ts +2 -3
- package/build/es/components/icon/icons/GreenCheckIcon.js +1 -1
- package/build/es/components/icon/icons/GreenCheckIcon.js.map +1 -1
- package/build/es/components/icon/icons/RedCrossIcon.d.ts +2 -3
- package/build/es/components/icon/icons/RedCrossIcon.js +1 -1
- package/build/es/components/icon/icons/RedCrossIcon.js.map +1 -1
- package/build/es/components/number-input/NumberInput.d.ts +7 -0
- package/build/es/components/number-input/NumberInput.js +2 -0
- package/build/es/components/number-input/NumberInput.js.map +1 -0
- package/build/es/components/number-input/index.d.ts +2 -0
- package/build/es/components/number-input/index.js +2 -0
- package/build/es/components/number-input/index.js.map +1 -0
- package/build/es/components/number-input/types.d.ts +20 -0
- package/build/es/components/number-input/types.js +2 -0
- package/build/es/components/number-input/types.js.map +1 -0
- package/build/es/components/text-area/BaseTextArea.js +1 -1
- package/build/es/components/text-area/BaseTextArea.js.map +1 -1
- package/build/es/components/text-area/counter.d.ts +2 -0
- package/build/es/components/text-area/counter.js +2 -0
- package/build/es/components/text-area/counter.js.map +1 -0
- package/build/es/components/text-area/types.d.ts +21 -1
- package/package.json +13 -1
- package/styles/components/countdown/countdown.css +2 -2
- package/styles/components/countdown/countdown.min.css +1 -1
- package/styles/components/feedback/feedback.css +2 -2
- package/styles/components/feedback/feedback.min.css +1 -1
- package/styles/components/file-input/file-input.css +9 -9
- package/styles/components/file-input/file-input.min.css +1 -1
- package/styles/components/icon/icon.css +28 -14
- package/styles/components/icon/icon.min.css +1 -1
- package/styles/components/icon/icon.scss +26 -20
- package/styles/components/input-group/input-group.css +2 -2
- package/styles/components/input-group/input-group.min.css +1 -1
- package/styles/components/list/list.css +34 -40
- package/styles/components/list/list.min.css +1 -1
- package/styles/components/list/list.scss +23 -25
- package/styles/components/loader/loader.css +6 -6
- package/styles/components/loader/loader.min.css +1 -1
- package/styles/components/loader/skeleton-loader.css +3 -3
- package/styles/components/loader/skeleton-loader.min.css +1 -1
- package/styles/components/message/message.css +2 -2
- package/styles/components/message/message.min.css +1 -1
- package/styles/components/number-input/_index.scss +2 -0
- package/styles/components/number-input/number-input.css +222 -0
- package/styles/components/number-input/number-input.min.css +1 -0
- package/styles/components/number-input/number-input.scss +121 -0
- package/styles/components/progress-bar/progress-bar.css +1 -1
- package/styles/components/progress-bar/progress-bar.min.css +1 -1
- package/styles/components/segmented-control/segmented-control.css +30 -16
- package/styles/components/segmented-control/segmented-control.min.css +1 -1
- package/styles/components/system-message/system-message.css +2 -2
- package/styles/components/system-message/system-message.min.css +1 -1
- package/styles/components/toast/toast.css +4 -4
- package/styles/components/toast/toast.min.css +1 -1
- package/styles/styles.css +305 -78
- package/styles/styles.min.css +1 -1
- package/styles/styles.scss +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.js","sources":["../../../../src/components/datepicker/DatePicker.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport React, {\n type ChangeEvent,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { formatDateString } from \"../../utilities/formatters/date/formatDate.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport Popover from \"../popover/Popover.js\";\nimport { BaseTextInput } from \"../text-input/BaseTextInput.js\";\nimport { Calendar } from \"./internal/Calendar.js\";\nimport { type DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport type { DatePickerProps, DateValidationError } from \"./types.js\";\nimport { formatInput, parseDateString } from \"./utils.js\";\nimport { isWithinLowerBound, isWithinUpperBound } from \"./validation.js\";\n\nconst setInputValue = (input: HTMLInputElement, value: string) => {\n const nativeSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n\n if (nativeSetter) {\n nativeSetter.call(input, value);\n } else {\n input.value = value;\n }\n};\n\nconst normalizeInputValue = (rawValue: string) => {\n const digits = rawValue.replace(/\\D/g, \"\");\n const partialCompactDate = formatDateString(digits, {\n partial: true,\n });\n const rawValueWithoutTrailingPunctuation = rawValue.replace(/\\D+$/, \"\");\n const compactDateCandidate =\n digits.length === 8 ? formatDateString(digits) : rawValue;\n const validCompactDate = parseDateString(compactDateCandidate)\n ? compactDateCandidate\n : null;\n const shouldRemoveFormatting =\n rawValue !== digits &&\n rawValueWithoutTrailingPunctuation === partialCompactDate &&\n parseDateString(rawValue) === undefined &&\n validCompactDate === null;\n\n return validCompactDate ?? (shouldRemoveFormatting ? digits : rawValue);\n};\n\nconst getInputValidationState = ({\n value,\n minDate,\n maxDate,\n}: {\n value: string;\n minDate?: Date;\n maxDate?: Date;\n}): { date: Date | null; error: DateValidationError | null } => {\n if (!value) {\n return { date: null, error: null };\n }\n\n const parsedDate = parseDateString(value);\n\n if (!parsedDate) {\n return { date: null, error: \"WRONG_FORMAT\" };\n }\n\n if (minDate && !isWithinLowerBound(parsedDate, minDate)) {\n return { date: parsedDate, error: \"OUTSIDE_LOWER_BOUND\" };\n }\n\n if (maxDate && !isWithinUpperBound(parsedDate, maxDate)) {\n return { date: parsedDate, error: \"OUTSIDE_UPPER_BOUND\" };\n }\n\n return { date: parsedDate, error: null };\n};\n\nexport const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(\n (props, forwardedInputRef) => {\n const {\n \"data-testautoid\": testAutoId,\n id,\n className = \"\",\n label = \"Velg dato\",\n labelProps,\n defaultValue,\n defaultShow = false,\n value,\n disableBeforeDate: disableBefore,\n disableAfterDate: disableAfter,\n yearsToShow,\n name,\n helpLabel,\n errorLabel,\n invalid,\n days,\n months,\n monthLabel,\n yearLabel,\n placeholder = \"dd.mm.åååå\",\n width = \"11.25rem\",\n onChange,\n onBlur,\n onFocus,\n onKeyDown,\n action,\n showCalendarLabel = \"Åpne kalender\",\n hideCalendarLabel = \"Lukk kalender\",\n supportLabelProps,\n tooltip,\n textInputProps,\n description,\n ...rest\n } = props;\n\n if (process.env.NODE_ENV !== \"production\" && value && defaultValue) {\n console.warn(\n \"DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.\",\n );\n }\n /// Input state\n\n const disableBeforeDate = parseDateString(disableBefore);\n const minDate = disableBeforeDate\n ? dayjs(disableBeforeDate).startOf(\"day\").toDate()\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? dayjs(disableAfterDate).startOf(\"day\").toDate()\n : undefined;\n\n const [date, setDate] = useState(\n getInitialDate(value, defaultValue, minDate, maxDate),\n );\n const [error, setError] = useState<DateValidationError | null>(null);\n\n /// Calendar state\n\n const [showCalendar, setShowCalendar] = useState(defaultShow);\n\n const calendarRef = useRef<HTMLDivElement>(null);\n const datepickerRef = useRef<HTMLDivElement>(null);\n\n /// Input events\n\n const iconButtonRef = useRef<HTMLButtonElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Hjelper for å gjøre det enklere å både forwarde refen men også bruke den selv internt\n const unifiedInputRef = useCallback(\n (instance: HTMLInputElement | null) => {\n inputRef.current = instance;\n if (forwardedInputRef) {\n if (typeof forwardedInputRef === \"function\") {\n forwardedInputRef(instance);\n } else {\n forwardedInputRef.current = instance;\n }\n }\n },\n [forwardedInputRef],\n );\n\n const handleFocus = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (!onFocus || !datepickerRef.current) {\n return;\n }\n\n const nextFocusIsInside = datepickerRef.current.contains(\n e.relatedTarget as Node,\n );\n if (!nextFocusIsInside) {\n onFocus(e, date, { error, value: e.target.value });\n }\n },\n [onFocus, date, error],\n );\n\n const handleBlur = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(e, date, { error, value: e.target.value });\n }\n },\n [onBlur, date, error],\n );\n\n const handleKeyDownAction = useCallback(\n (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Escape\") {\n setShowCalendar(false);\n e.preventDefault();\n e.stopPropagation();\n }\n\n if (action?.onKeyDown) {\n action.onKeyDown(e);\n }\n },\n [action],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const rawValue = e.currentTarget.value;\n const formattedValue = normalizeInputValue(rawValue);\n\n if (formattedValue !== rawValue) {\n setInputValue(e.currentTarget, formattedValue);\n }\n\n const { date: nextDate, error: nextError } =\n getInputValidationState({\n value: formattedValue,\n minDate,\n maxDate,\n });\n\n if (nextDate && !nextError) {\n setShowCalendar(false);\n }\n\n setError(nextError);\n setDate(nextDate);\n\n if (onChange) {\n onChange(e, nextDate, {\n error: nextError,\n value: formattedValue,\n });\n }\n },\n [onChange, minDate, maxDate],\n );\n\n /// Calendar events\n\n const clickCalendar = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n flushSync(() => {\n setShowCalendar(!showCalendar);\n });\n\n const calendarEl = calendarRef.current;\n const button =\n calendarEl &&\n (calendarEl.querySelector(\n '[aria-pressed=\"true\"]',\n ) as HTMLButtonElement);\n // Make sure the popover-modal is correctly positioned before focusing a button\n // so we avoid accidentally scrolling to the top of the page\n window.requestAnimationFrame(() => button?.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [showCalendar, action],\n );\n\n const handleClickCalendarDay = useCallback(\n ({ date }: DateInfo) => {\n setShowCalendar(false);\n setDate(date);\n\n if (inputRef.current) {\n const node = inputRef.current;\n\n node.value = formatInput(date);\n\n // Simulér et change-event så APIet blir så likt som mulig en endring av inputfeltet\n const event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n\n node.focus();\n\n if (onChange) {\n // Det er ikke helt sant at dette er et React.SyntheticEvent, men it's fine – probably?\n // Den har tingene man kan forvente, men hvis du gjør serdeles fancy ting med events\n // så kan det hende du må utvide denne for å dekke behovet ditt.\n onChange(\n event as unknown as ChangeEvent<HTMLInputElement>,\n date,\n {\n error: null,\n value: node.value,\n },\n );\n }\n }\n },\n [onChange],\n );\n\n const handleTabOutsideCalendar = useCallback((e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current?.focus();\n }, []);\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className)}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n render={(inputProps) => (\n <BaseTextInput\n data-focused={showCalendar ? \"true\" : undefined}\n ref={unifiedInputRef}\n data-testid=\"jkl-datepicker__input\"\n data-testautoid={testAutoId}\n className=\"jkl-datepicker__input\"\n name={name}\n defaultValue={defaultValue}\n value={value}\n type=\"text\"\n placeholder={placeholder}\n width={width}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n actionButton={\n <Popover\n positionReference={inputRef}\n open={showCalendar}\n onOpenChange={() =>\n setShowCalendar(!showCalendar)\n }\n offset={8}\n >\n <Popover.Trigger\n {...action}\n data-testid=\"jkl-datepicker__trigger\"\n className=\"jkl-text-input-action-button\"\n title={\n showCalendar\n ? hideCalendarLabel\n : showCalendarLabel\n }\n tabIndex={0}\n onClick={clickCalendar}\n onKeyDown={handleKeyDownAction}\n asChild\n >\n <IconButton>\n <CalendarIcon />\n </IconButton>\n </Popover.Trigger>\n <Popover.Content initialFocus={-1} padding={24}>\n <Calendar\n ref={calendarRef}\n date={date}\n minDate={minDate}\n maxDate={maxDate}\n days={days}\n months={months}\n monthLabel={monthLabel}\n yearLabel={yearLabel}\n yearsToShow={yearsToShow}\n onDateSelected={handleClickCalendarDay}\n onTabOutside={handleTabOutsideCalendar}\n />\n </Popover.Content>\n </Popover>\n }\n {...textInputProps}\n {...inputProps}\n aria-invalid={invalid || !!errorLabel}\n />\n )}\n />\n );\n },\n);\n\nDatePicker.displayName = \"DatePicker\";\n"],"names":["DatePicker","forwardRef","props","forwardedInputRef","testAutoId","id","className","label","labelProps","defaultValue","defaultShow","value","disableBeforeDate","disableBefore","disableAfterDate","disableAfter","yearsToShow","name","helpLabel","errorLabel","invalid","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltip","textInputProps","description","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","dayjs","startOf","toDate","maxDate","date","setDate","useState","getInitialDate","error","setError","showCalendar","setShowCalendar","calendarRef","useRef","datepickerRef","iconButtonRef","inputRef","unifiedInputRef","useCallback","instance","current","handleFocus","e","contains","relatedTarget","target","handleBlur","handleKeyDownAction","key","preventDefault","stopPropagation","handleChange","rawValue","currentTarget","formattedValue","digits","replace","partialCompactDate","formatDateString","partial","rawValueWithoutTrailingPunctuation","compactDateCandidate","length","validCompactDate","shouldRemoveFormatting","normalizeInputValue","input","nativeSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","setInputValue","nextDate","nextError","parsedDate","isWithinLowerBound","isWithinUpperBound","getInputValidationState","clickCalendar","flushSync","calendarEl","button","querySelector","window","requestAnimationFrame","focus","onClick","handleClickCalendarDay","node","formatInput","event","document","createEvent","initEvent","dispatchEvent","handleTabOutsideCalendar","jsx","InputGroup","clsx","ref","render","inputProps","BaseTextInput","type","actionButton","jsxs","Popover","positionReference","open","onOpenChange","offset","children","Trigger","title","tabIndex","asChild","IconButton","CalendarIcon","Content","initialFocus","padding","Calendar","onDateSelected","onTabOutside","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DatePicker.js","sources":["../../../../src/components/datepicker/DatePicker.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport React, {\n type ChangeEvent,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { formatDateString } from \"../../utilities/formatters/date/formatDate.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport Popover from \"../popover/Popover.js\";\nimport { BaseTextInput } from \"../text-input/BaseTextInput.js\";\nimport { Calendar } from \"./internal/Calendar.js\";\nimport { type DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport type { DatePickerProps, DateValidationError } from \"./types.js\";\nimport { formatInput, parseDateString } from \"./utils.js\";\nimport { isWithinLowerBound, isWithinUpperBound } from \"./validation.js\";\n\nconst setInputValue = (input: HTMLInputElement, value: string) => {\n const nativeSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n\n if (nativeSetter) {\n nativeSetter.call(input, value);\n } else {\n input.value = value;\n }\n};\n\nconst normalizeInputValue = (\n rawValue: string,\n shouldStripAutoFormatting: boolean,\n) => {\n const digits = rawValue.replace(/\\D/g, \"\");\n const partialCompactDate = formatDateString(digits, {\n partial: true,\n });\n const rawValueWithoutTrailingPunctuation = rawValue.replace(/\\D+$/, \"\");\n const compactDateCandidate =\n digits.length === 8 ? formatDateString(digits) : rawValue;\n const validCompactDate = parseDateString(compactDateCandidate)\n ? compactDateCandidate\n : null;\n const shouldRemoveFormatting =\n shouldStripAutoFormatting &&\n rawValue !== digits &&\n rawValueWithoutTrailingPunctuation === partialCompactDate &&\n parseDateString(rawValue) === undefined &&\n validCompactDate === null;\n\n return validCompactDate ?? (shouldRemoveFormatting ? digits : rawValue);\n};\n\nconst getInputValidationState = ({\n value,\n minDate,\n maxDate,\n}: {\n value: string;\n minDate?: Date;\n maxDate?: Date;\n}): { date: Date | null; error: DateValidationError | null } => {\n if (!value) {\n return { date: null, error: null };\n }\n\n const parsedDate = parseDateString(value);\n\n if (!parsedDate) {\n return { date: null, error: \"WRONG_FORMAT\" };\n }\n\n if (minDate && !isWithinLowerBound(parsedDate, minDate)) {\n return { date: parsedDate, error: \"OUTSIDE_LOWER_BOUND\" };\n }\n\n if (maxDate && !isWithinUpperBound(parsedDate, maxDate)) {\n return { date: parsedDate, error: \"OUTSIDE_UPPER_BOUND\" };\n }\n\n return { date: parsedDate, error: null };\n};\n\nexport const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(\n (props, forwardedInputRef) => {\n const {\n \"data-testautoid\": testAutoId,\n id,\n className = \"\",\n label = \"Velg dato\",\n labelProps,\n defaultValue,\n defaultShow = false,\n value,\n disableBeforeDate: disableBefore,\n disableAfterDate: disableAfter,\n yearsToShow,\n name,\n helpLabel,\n errorLabel,\n invalid,\n days,\n months,\n monthLabel,\n yearLabel,\n placeholder = \"dd.mm.åååå\",\n width = \"11.25rem\",\n onChange,\n onBlur,\n onFocus,\n onKeyDown,\n action,\n showCalendarLabel = \"Åpne kalender\",\n hideCalendarLabel = \"Lukk kalender\",\n supportLabelProps,\n tooltip,\n textInputProps,\n description,\n ...rest\n } = props;\n\n if (process.env.NODE_ENV !== \"production\" && value && defaultValue) {\n console.warn(\n \"DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.\",\n );\n }\n /// Input state\n\n const disableBeforeDate = parseDateString(disableBefore);\n const minDate = disableBeforeDate\n ? dayjs(disableBeforeDate).startOf(\"day\").toDate()\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? dayjs(disableAfterDate).startOf(\"day\").toDate()\n : undefined;\n\n const [date, setDate] = useState(\n getInitialDate(value, defaultValue, minDate, maxDate),\n );\n const [error, setError] = useState<DateValidationError | null>(null);\n\n /// Calendar state\n\n const [showCalendar, setShowCalendar] = useState(defaultShow);\n\n const calendarRef = useRef<HTMLDivElement>(null);\n const datepickerRef = useRef<HTMLDivElement>(null);\n\n /// Input events\n\n const iconButtonRef = useRef<HTMLButtonElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const didAutoFormatCompactInputRef = useRef(false);\n\n // Hjelper for å gjøre det enklere å både forwarde refen men også bruke den selv internt\n const unifiedInputRef = useCallback(\n (instance: HTMLInputElement | null) => {\n inputRef.current = instance;\n if (forwardedInputRef) {\n if (typeof forwardedInputRef === \"function\") {\n forwardedInputRef(instance);\n } else {\n forwardedInputRef.current = instance;\n }\n }\n },\n [forwardedInputRef],\n );\n\n const handleFocus = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (!onFocus || !datepickerRef.current) {\n return;\n }\n\n const nextFocusIsInside = datepickerRef.current.contains(\n e.relatedTarget as Node,\n );\n if (!nextFocusIsInside) {\n onFocus(e, date, { error, value: e.target.value });\n }\n },\n [onFocus, date, error],\n );\n\n const handleBlur = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(e, date, { error, value: e.target.value });\n }\n },\n [onBlur, date, error],\n );\n\n const handleKeyDownAction = useCallback(\n (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Escape\") {\n setShowCalendar(false);\n e.preventDefault();\n e.stopPropagation();\n }\n\n if (action?.onKeyDown) {\n action.onKeyDown(e);\n }\n },\n [action],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const rawValue = e.currentTarget.value;\n const formattedValue = normalizeInputValue(\n rawValue,\n didAutoFormatCompactInputRef.current,\n );\n\n if (formattedValue !== rawValue) {\n setInputValue(e.currentTarget, formattedValue);\n }\n\n const digits = rawValue.replace(/\\D/g, \"\");\n didAutoFormatCompactInputRef.current =\n rawValue === digits &&\n formattedValue === formatDateString(digits) &&\n formattedValue !== rawValue &&\n parseDateString(formattedValue) !== undefined;\n\n const { date: nextDate, error: nextError } =\n getInputValidationState({\n value: formattedValue,\n minDate,\n maxDate,\n });\n\n if (nextDate && !nextError) {\n setShowCalendar(false);\n }\n\n setError(nextError);\n setDate(nextDate);\n\n if (onChange) {\n onChange(e, nextDate, {\n error: nextError,\n value: formattedValue,\n });\n }\n },\n [onChange, minDate, maxDate],\n );\n\n /// Calendar events\n\n const clickCalendar = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n flushSync(() => {\n setShowCalendar(!showCalendar);\n });\n\n const calendarEl = calendarRef.current;\n const button =\n calendarEl &&\n (calendarEl.querySelector(\n '[aria-pressed=\"true\"]',\n ) as HTMLButtonElement);\n // Make sure the popover-modal is correctly positioned before focusing a button\n // so we avoid accidentally scrolling to the top of the page\n window.requestAnimationFrame(() => button?.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [showCalendar, action],\n );\n\n const handleClickCalendarDay = useCallback(\n ({ date }: DateInfo) => {\n setShowCalendar(false);\n setDate(date);\n\n if (inputRef.current) {\n const node = inputRef.current;\n\n didAutoFormatCompactInputRef.current = false;\n node.value = formatInput(date);\n\n // Simulér et change-event så APIet blir så likt som mulig en endring av inputfeltet\n const event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n\n node.focus();\n\n if (onChange) {\n // Det er ikke helt sant at dette er et React.SyntheticEvent, men it's fine – probably?\n // Den har tingene man kan forvente, men hvis du gjør serdeles fancy ting med events\n // så kan det hende du må utvide denne for å dekke behovet ditt.\n onChange(\n event as unknown as ChangeEvent<HTMLInputElement>,\n date,\n {\n error: null,\n value: node.value,\n },\n );\n }\n }\n },\n [onChange],\n );\n\n const handleTabOutsideCalendar = useCallback((e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current?.focus();\n }, []);\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className)}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n render={(inputProps) => (\n <BaseTextInput\n data-focused={showCalendar ? \"true\" : undefined}\n ref={unifiedInputRef}\n data-testid=\"jkl-datepicker__input\"\n data-testautoid={testAutoId}\n className=\"jkl-datepicker__input\"\n name={name}\n defaultValue={defaultValue}\n value={value}\n type=\"text\"\n placeholder={placeholder}\n width={width}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n actionButton={\n <Popover\n positionReference={inputRef}\n open={showCalendar}\n onOpenChange={() =>\n setShowCalendar(!showCalendar)\n }\n offset={8}\n >\n <Popover.Trigger\n {...action}\n data-testid=\"jkl-datepicker__trigger\"\n className=\"jkl-text-input-action-button\"\n title={\n showCalendar\n ? hideCalendarLabel\n : showCalendarLabel\n }\n tabIndex={0}\n onClick={clickCalendar}\n onKeyDown={handleKeyDownAction}\n asChild\n >\n <IconButton>\n <CalendarIcon />\n </IconButton>\n </Popover.Trigger>\n <Popover.Content initialFocus={-1} padding={24}>\n <Calendar\n ref={calendarRef}\n date={date}\n minDate={minDate}\n maxDate={maxDate}\n days={days}\n months={months}\n monthLabel={monthLabel}\n yearLabel={yearLabel}\n yearsToShow={yearsToShow}\n onDateSelected={handleClickCalendarDay}\n onTabOutside={handleTabOutsideCalendar}\n />\n </Popover.Content>\n </Popover>\n }\n {...textInputProps}\n {...inputProps}\n aria-invalid={invalid || !!errorLabel}\n />\n )}\n />\n );\n },\n);\n\nDatePicker.displayName = \"DatePicker\";\n"],"names":["DatePicker","forwardRef","props","forwardedInputRef","testAutoId","id","className","label","labelProps","defaultValue","defaultShow","value","disableBeforeDate","disableBefore","disableAfterDate","disableAfter","yearsToShow","name","helpLabel","errorLabel","invalid","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltip","textInputProps","description","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","dayjs","startOf","toDate","maxDate","date","setDate","useState","getInitialDate","error","setError","showCalendar","setShowCalendar","calendarRef","useRef","datepickerRef","iconButtonRef","inputRef","didAutoFormatCompactInputRef","unifiedInputRef","useCallback","instance","current","handleFocus","e","contains","relatedTarget","target","handleBlur","handleKeyDownAction","key","preventDefault","stopPropagation","handleChange","rawValue","currentTarget","formattedValue","shouldStripAutoFormatting","digits","replace","partialCompactDate","formatDateString","partial","rawValueWithoutTrailingPunctuation","compactDateCandidate","length","validCompactDate","shouldRemoveFormatting","normalizeInputValue","input","nativeSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","setInputValue","nextDate","nextError","parsedDate","isWithinLowerBound","isWithinUpperBound","getInputValidationState","clickCalendar","flushSync","calendarEl","button","querySelector","window","requestAnimationFrame","focus","onClick","handleClickCalendarDay","node","formatInput","event","document","createEvent","initEvent","dispatchEvent","handleTabOutsideCalendar","jsx","InputGroup","clsx","ref","render","inputProps","BaseTextInput","type","actionButton","jsxs","Popover","positionReference","open","onOpenChange","offset","children","Trigger","title","tabIndex","asChild","IconButton","CalendarIcon","Content","initialFocus","padding","Calendar","onDateSelected","onTabOutside","displayName"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { PolymorphicPropsWithRef } from '../../utilities/polymorphism/polymorphism.js';
|
|
3
3
|
import { IconVariant } from './types.js';
|
|
4
|
-
type IconComponentProps<ElementType extends
|
|
4
|
+
type IconComponentProps<ElementType extends "span" | "div"> = PolymorphicPropsWithRef<ElementType, {
|
|
5
5
|
"data-testid"?: string;
|
|
6
6
|
/**
|
|
7
7
|
* Størrelsesvarianten til ikonet. `"small"` er 16px med 20px bounding box, og `"medium"` er 20px med 24px bounding box.
|
|
@@ -17,7 +17,7 @@ type IconComponentProps<ElementType extends Extract<React.ElementType, "span" |
|
|
|
17
17
|
className?: string;
|
|
18
18
|
style?: React.CSSProperties;
|
|
19
19
|
}>;
|
|
20
|
-
export type IconComponent = (<ElementType extends
|
|
20
|
+
export type IconComponent = (<ElementType extends "span" | "div" = "span">(props: IconComponentProps<ElementType>) => React.ReactElement | null) & {
|
|
21
21
|
displayName?: string;
|
|
22
22
|
};
|
|
23
23
|
export declare const Icon: IconComponent;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as r}from"react/jsx-runtime";import{c as
|
|
1
|
+
import{jsx as r}from"react/jsx-runtime";import{c as a}from"../../../clsx-BeLtu-UY.js";import i from"react";const o=i.forwardRef(function(i,o){const{as:n="span",bold:s,children:c,className:e,filled:l,variant:t,...d}=i,f=a("jkl-icon",e,{"jkl-icon--filled":l,"jkl-icon--bold":s});return r("div"===n?"div":"span",{"aria-hidden":!0,ref:o,className:f,...d,children:c})});export{o as Icon};
|
|
2
2
|
//# sourceMappingURL=Icon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.js","sources":["../../../../src/components/icon/Icon.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React from \"react\";\nimport type {\n PolymorphicPropsWithRef,\n PolymorphicRef,\n} from \"../../utilities/polymorphism/polymorphism.js\";\nimport type { IconVariant } from \"./types.js\";\n\ntype IconComponentProps<\n ElementType extends
|
|
1
|
+
{"version":3,"file":"Icon.js","sources":["../../../../src/components/icon/Icon.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React from \"react\";\nimport type {\n PolymorphicPropsWithRef,\n PolymorphicRef,\n} from \"../../utilities/polymorphism/polymorphism.js\";\nimport type { IconVariant } from \"./types.js\";\n\ntype IconComponentProps<\n ElementType extends \"span\" | \"div\",\n> = PolymorphicPropsWithRef<\n ElementType,\n {\n \"data-testid\"?: string;\n /**\n * Størrelsesvarianten til ikonet. `\"small\"` er 16px med 20px bounding box, og `\"medium\"` er 20px med 24px bounding box.\n * `\"inherit\"` setter størrelsen til ikonet (ikke bounding box) lik skriftstørrelsen (1em).\n */\n variant?: IconVariant;\n /**\n * Angir om ikonet skal vises i fet versjon\n * @default false\n */\n bold?: boolean;\n filled?: boolean;\n className?: string;\n style?: React.CSSProperties;\n }\n>;\n\nexport type IconComponent = (<\n ElementType extends \"span\" | \"div\" = \"span\",\n>(\n props: IconComponentProps<ElementType>,\n) => React.ReactElement | null) & { displayName?: string };\n\nexport const Icon: IconComponent = React.forwardRef(function Icon<\n ElementType extends \"span\" | \"div\" = \"span\",\n>(props: IconComponentProps<ElementType>, ref?: PolymorphicRef<ElementType>) {\n const {\n as = \"span\",\n bold,\n children,\n className,\n filled,\n variant,\n ...iconProps\n } = props;\n const iconClassName = clsx(\"jkl-icon\", className, {\n \"jkl-icon--filled\": filled,\n \"jkl-icon--bold\": bold,\n });\n\n if (as === \"div\") {\n return (\n <div\n aria-hidden\n ref={ref as PolymorphicRef<\"div\">}\n className={iconClassName}\n {...(iconProps as React.HTMLAttributes<HTMLDivElement>)}\n >\n {children}\n </div>\n );\n }\n\n return (\n <span\n aria-hidden\n ref={ref as PolymorphicRef<\"span\">}\n className={iconClassName}\n {...(iconProps as React.HTMLAttributes<HTMLSpanElement>)}\n >\n {children}\n </span>\n );\n}) as IconComponent;\n"],"names":["Icon","React","forwardRef","props","ref","as","bold","children","className","filled","variant","iconProps","iconClassName","clsx","jsx"],"mappings":"2GAoCO,MAAMA,EAAsBC,EAAMC,WAAW,SAElDC,EAAwCC,GACtC,MACIC,GAAAA,EAAK,OACLC,KAAAA,EACAC,SAAAA,EACAC,UAAAA,EACAC,OAAAA,EACAC,QAAAA,KACGC,GACHR,EACES,EAAgBC,EAAK,WAAYL,EAAW,CAC9C,mBAAoBC,EACpB,iBAAkBH,IAGtB,OAEQQ,EAFG,QAAPT,EAEK,MAYJ,OAZI,CACG,eAAW,EACXD,IAAAA,EACAI,UAAWI,KACND,EAEJJ,SAAAA,GAejB"}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare const GreenCheckIcon: FC<IconProps>;
|
|
1
|
+
import { IconComponent } from '../Icon.js';
|
|
2
|
+
export declare const GreenCheckIcon: IconComponent;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as c}from"react/jsx-runtime";import{c as e}from"../../../../clsx-BeLtu-UY.js";import"react";import{Icon as r}from"../Icon.js";const s=s=>c(r,{...s,className:e("jkl-icon-green-check",s.className),children:""});s.displayName="GreenCheckIcon";export{s as GreenCheckIcon};
|
|
2
2
|
//# sourceMappingURL=GreenCheckIcon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GreenCheckIcon.js","sources":["../../../../../src/components/icon/icons/GreenCheckIcon.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React
|
|
1
|
+
{"version":3,"file":"GreenCheckIcon.js","sources":["../../../../../src/components/icon/icons/GreenCheckIcon.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React from \"react\";\nimport { Icon, type IconComponent } from \"../Icon.js\";\nimport type { IconProps } from \"../types.js\";\n\nexport const GreenCheckIcon: IconComponent = (props: IconProps) => (\n <Icon {...props} className={clsx(\"jkl-icon-green-check\", props.className)}>\n {\"\\ue5ca\"}\n </Icon>\n);\nGreenCheckIcon.displayName = \"GreenCheckIcon\";\n"],"names":["GreenCheckIcon","props","jsx","Icon","className","clsx","children","displayName"],"mappings":"yIAKO,MAAMA,EAAiCC,GAC1CC,EAACC,EAAA,IAASF,EAAOG,UAAWC,EAAK,uBAAwBJ,EAAMG,WAC1DE,SAAA,MAGTN,EAAeO,YAAc"}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare const RedCrossIcon: FC<IconProps>;
|
|
1
|
+
import { IconComponent } from '../Icon.js';
|
|
2
|
+
export declare const RedCrossIcon: IconComponent;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as s
|
|
1
|
+
import{jsx as s}from"react/jsx-runtime";import{c as o}from"../../../../clsx-BeLtu-UY.js";import"react";import{Icon as r}from"../Icon.js";const c=c=>s(r,{...c,className:o("jkl-icon-red-cross",c.className),children:""});c.displayName="RedCrossIcon";export{c as RedCrossIcon};
|
|
2
2
|
//# sourceMappingURL=RedCrossIcon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RedCrossIcon.js","sources":["../../../../../src/components/icon/icons/RedCrossIcon.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React
|
|
1
|
+
{"version":3,"file":"RedCrossIcon.js","sources":["../../../../../src/components/icon/icons/RedCrossIcon.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React from \"react\";\nimport { Icon, type IconComponent } from \"../Icon.js\";\nimport type { IconProps } from \"../types.js\";\n\nexport const RedCrossIcon: IconComponent = (props: IconProps) => (\n <Icon {...props} className={clsx(\"jkl-icon-red-cross\", props.className)}>\n {\"\\ue5cd\"}\n </Icon>\n);\nRedCrossIcon.displayName = \"RedCrossIcon\";\n"],"names":["RedCrossIcon","props","jsx","Icon","className","clsx","children","displayName"],"mappings":"yIAKO,MAAMA,EAA+BC,GACxCC,EAACC,EAAA,IAASF,EAAOG,UAAWC,EAAK,qBAAsBJ,EAAMG,WACxDE,SAAA,MAGTN,EAAaO,YAAc"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export declare const NumberInput: React.ForwardRefExoticComponent<Omit<import('../input-group/types.js').InputGroupProps, "children" | "inline" | "render"> & Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "children"> & {
|
|
3
|
+
align?: "left" | "right";
|
|
4
|
+
width?: string;
|
|
5
|
+
inputClassName?: string;
|
|
6
|
+
stepper?: boolean;
|
|
7
|
+
} & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jsx as n,jsxs as o}from"react/jsx-runtime";import{c as i}from"../../../clsx-BeLtu-UY.js";import{forwardRef as e,useRef as r,useState as t}from"react";import{mergeRefs as s}from"../../utilities/mergeRefs.js";import"../icon/Icon.js";import"../icon/icons/animated/ArrowVerticalAnimated.js";import"../icon/icons/animated/ArrowHorizontalAnimated.js";import"../icon/icons/animated/PlusRemoveAnimated.js";import"../icon/icons/ArrowDownIcon.js";import"../icon/icons/ArrowLeftIcon.js";import"../icon/icons/ArrowNorthEastIcon.js";import"../icon/icons/ArrowRightIcon.js";import"../icon/icons/ArrowUpIcon.js";import"../icon/icons/CalendarIcon.js";import"../icon/icons/CheckIcon.js";import"../icon/icons/ChevronDownIcon.js";import"../icon/icons/ChevronLeftIcon.js";import"../icon/icons/ChevronRightIcon.js";import"../icon/icons/ChevronUpIcon.js";import"../icon/icons/CloseIcon.js";import"../icon/icons/CopyIcon.js";import"../icon/icons/DotsIcon.js";import"../icon/icons/DragIcon.js";import"../icon/icons/ErrorIcon.js";import"../icon/icons/GreenCheckIcon.js";import"../icon/icons/HamburgerIcon.js";import"../icon/icons/InfoIcon.js";import"../icon/icons/LinkIcon.js";import{MinusIcon as c}from"../icon/icons/MinusIcon.js";import"../icon/icons/OpenInNewIcon.js";import"../icon/icons/PenIcon.js";import{PlusIcon as a}from"../icon/icons/PlusIcon.js";import"../icon/icons/QuestionIcon.js";import"../icon/icons/RedCrossIcon.js";import"../icon/icons/SearchIcon.js";import"../icon/icons/SuccessIcon.js";import"../icon/icons/ThumbDownIcon.js";import"../icon/icons/ThumbUpIcon.js";import"../icon/icons/TrashCanIcon.js";import"../icon/icons/WarningIcon.js";import{InputGroup as p}from"../input-group/InputGroup.js";const m={decrement:{label:"Senk verdien",Icon:c},increment:{label:"Øk verdien",Icon:a}};function l({direction:o,disabled:i,onClick:e}){const{label:r,Icon:t}=m[o];return n("button",{type:"button",className:"jkl-button jkl-button--ghost","aria-label":r,"data-direction":o,onPointerDown:n=>n.preventDefault(),onClick:e,disabled:i,children:n("span",{"aria-hidden":"true",children:n(t,{})})})}const u=e((e,c)=>{const{"data-size":a,"data-testautoid":m,"data-testid":u,align:d="left",id:b,label:j,className:I,style:h,errorLabel:N,helpLabel:f,inputClassName:v,labelProps:w,supportLabelProps:k,stepper:C=!1,tooltip:g,description:y,width:A,onChange:_,...L}=e,P=r(null),D=s(P,c),[R,x]=t(L.defaultValue),E=void 0!==L.value?L.value:R,F=n=>{void 0===L.value&&x(n.target.value),_?.(n)},S=function(n){return"number"==typeof n?n:"string"==typeof n&&""!==n.trim()?Number(n):Number.NaN}(E),U=void 0!==L.min?Number(L.min):Number.NaN,z=void 0!==L.max?Number(L.max):Number.NaN,G=Number.isFinite(S)&&Number.isFinite(U)&&S<=U,O=Number.isFinite(S)&&Number.isFinite(z)&&S>=z,T=h||A?{...h,...A?{width:A}:void 0}:void 0,H={id:b,label:j,errorLabel:N,helpLabel:f,labelProps:w,supportLabelProps:k,tooltip:g,description:y},M=n=>{const o=P.current;if(!o||o.disabled||o.readOnly)return;const i=o.value;o.focus();try{"increment"===n?o.stepUp():o.stepDown()}catch{return}o.value!==i&&o.dispatchEvent(new Event("input",{bubbles:!0}))},V=L.disabled||L.readOnly;return n(p,{...H,className:i(I,"jkl-number-input"),"data-size":a,"data-testid":u??"jkl-number-input",render:e=>o("div",{className:i("jkl-number-input__wrapper",{"jkl-number-input__wrapper--stepper":C}),"data-invalid":e["aria-invalid"],style:T,children:[C&&n(l,{direction:"decrement",disabled:V||G,onClick:()=>M("decrement")}),n("input",{...e,...L,ref:D,type:"number",onChange:F,className:i("jkl-number-input__input",{"jkl-number-input__input--stepper":C,"jkl-number-input__input--align-right":!C&&"right"===d},v),"data-testautoid":m}),C&&n(l,{direction:"increment",disabled:V||O,onClick:()=>M("increment")})]})})});u.displayName="NumberInput";export{u as NumberInput};
|
|
2
|
+
//# sourceMappingURL=NumberInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NumberInput.js","sources":["../../../../src/components/number-input/NumberInput.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n type ComponentType,\n forwardRef,\n useRef,\n useState,\n} from \"react\";\nimport { mergeRefs } from \"../../utilities/mergeRefs.js\";\nimport { MinusIcon, PlusIcon } from \"../icon/index.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport type { NumberInputProps } from \"./types.js\";\n\ntype NumberInputValue = string | number | readonly string[] | undefined;\n\ntype StepDirection = \"increment\" | \"decrement\";\n\nconst stepperConfig: Record<\n StepDirection,\n { label: string; Icon: ComponentType }\n> = {\n decrement: { label: \"Senk verdien\", Icon: MinusIcon },\n increment: { label: \"Øk verdien\", Icon: PlusIcon },\n};\n\nfunction toNumeric(value: NumberInputValue): number {\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\" && value.trim() !== \"\") {\n return Number(value);\n }\n return Number.NaN;\n}\n\ntype StepperButtonProps = {\n direction: StepDirection;\n disabled: boolean;\n onClick: () => void;\n};\n\nfunction StepperButton({ direction, disabled, onClick }: StepperButtonProps) {\n const { label, Icon } = stepperConfig[direction];\n\n return (\n <button\n type=\"button\"\n className=\"jkl-button jkl-button--ghost\"\n aria-label={label}\n data-direction={direction}\n onPointerDown={(event) => event.preventDefault()}\n onClick={onClick}\n disabled={disabled}\n >\n <span aria-hidden=\"true\">\n <Icon />\n </span>\n </button>\n );\n}\n\nexport const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(\n (props, ref) => {\n const {\n \"data-size\": dataSize,\n \"data-testautoid\": testAutoId,\n \"data-testid\": dataTestId,\n align = \"left\",\n id,\n label,\n className,\n style,\n errorLabel,\n helpLabel,\n inputClassName,\n labelProps,\n supportLabelProps,\n stepper = false,\n tooltip,\n description,\n width,\n onChange,\n ...rest\n } = props;\n const internalRef = useRef<HTMLInputElement>(null);\n const mergedRef = mergeRefs(internalRef, ref);\n const [uncontrolledValue, setUncontrolledValue] =\n useState<NumberInputValue>(rest.defaultValue);\n\n // I kontrollert bruk må vi lese direkte fra `value` for at disabled-\n // state på stepper-knappene skal følge prop-en i samme render. Bruker\n // intern state som fallback for ukontrollert bruk.\n const effectiveValue =\n rest.value !== undefined ? rest.value : uncontrolledValue;\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (rest.value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n onChange?.(event);\n };\n\n const numericValue = toNumeric(effectiveValue);\n const minNumeric =\n rest.min !== undefined ? Number(rest.min) : Number.NaN;\n const maxNumeric =\n rest.max !== undefined ? Number(rest.max) : Number.NaN;\n const isAtOrBelowMin =\n Number.isFinite(numericValue) &&\n Number.isFinite(minNumeric) &&\n numericValue <= minNumeric;\n const isAtOrAboveMax =\n Number.isFinite(numericValue) &&\n Number.isFinite(maxNumeric) &&\n numericValue >= maxNumeric;\n\n const inputWrapperStyle =\n style || width\n ? {\n ...style,\n ...(width ? { width } : undefined),\n }\n : undefined;\n const inputGroupProps = {\n id,\n label,\n errorLabel,\n helpLabel,\n labelProps,\n supportLabelProps,\n tooltip,\n description,\n };\n\n const triggerStep = (direction: StepDirection) => {\n const input = internalRef.current;\n\n if (!input || input.disabled || input.readOnly) {\n return;\n }\n\n const previousValue = input.value;\n input.focus();\n\n try {\n if (direction === \"increment\") {\n input.stepUp();\n } else {\n input.stepDown();\n }\n } catch {\n return;\n }\n\n if (input.value === previousValue) {\n return;\n }\n\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n };\n\n const stepperDisabled = rest.disabled || rest.readOnly;\n\n return (\n <InputGroup\n {...inputGroupProps}\n className={clsx(className, \"jkl-number-input\")}\n data-size={dataSize}\n data-testid={dataTestId ?? \"jkl-number-input\"}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-number-input__wrapper\", {\n \"jkl-number-input__wrapper--stepper\": stepper,\n })}\n data-invalid={inputProps[\"aria-invalid\"]}\n style={inputWrapperStyle}\n >\n {stepper && (\n <StepperButton\n direction=\"decrement\"\n disabled={stepperDisabled || isAtOrBelowMin}\n onClick={() => triggerStep(\"decrement\")}\n />\n )}\n <input\n {...inputProps}\n {...rest}\n ref={mergedRef}\n type=\"number\"\n onChange={handleChange}\n className={clsx(\n \"jkl-number-input__input\",\n {\n \"jkl-number-input__input--stepper\": stepper,\n \"jkl-number-input__input--align-right\":\n !stepper && align === \"right\",\n },\n inputClassName,\n )}\n data-testautoid={testAutoId}\n />\n {stepper && (\n <StepperButton\n direction=\"increment\"\n disabled={stepperDisabled || isAtOrAboveMax}\n onClick={() => triggerStep(\"increment\")}\n />\n )}\n </div>\n )}\n />\n );\n },\n);\n\nNumberInput.displayName = \"NumberInput\";\n"],"names":["stepperConfig","decrement","label","Icon","MinusIcon","increment","PlusIcon","StepperButton","direction","disabled","onClick","jsx","type","className","onPointerDown","event","preventDefault","children","NumberInput","forwardRef","props","ref","dataSize","testAutoId","dataTestId","align","id","style","errorLabel","helpLabel","inputClassName","labelProps","supportLabelProps","stepper","tooltip","description","width","onChange","rest","internalRef","useRef","mergedRef","mergeRefs","uncontrolledValue","setUncontrolledValue","useState","defaultValue","effectiveValue","value","handleChange","target","numericValue","trim","Number","NaN","toNumeric","minNumeric","min","maxNumeric","max","isAtOrBelowMin","isFinite","isAtOrAboveMax","inputWrapperStyle","inputGroupProps","triggerStep","input","current","readOnly","previousValue","focus","stepUp","stepDown","dispatchEvent","Event","bubbles","stepperDisabled","InputGroup","clsx","render","inputProps","jsxs","displayName"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { InputHTMLAttributes } from 'react';
|
|
2
|
+
import { InputGroupProps } from '../input-group/types.js';
|
|
3
|
+
export type NumberInputProps = Omit<InputGroupProps, "children" | "inline" | "render"> & Omit<InputHTMLAttributes<HTMLInputElement>, "children" | "type"> & {
|
|
4
|
+
/**
|
|
5
|
+
* Justerer teksten i inputfeltet.
|
|
6
|
+
* @default "left"
|
|
7
|
+
*/
|
|
8
|
+
align?: "left" | "right";
|
|
9
|
+
/**
|
|
10
|
+
* CSS-verdi for bredden til input-feltet.
|
|
11
|
+
*/
|
|
12
|
+
width?: string;
|
|
13
|
+
inputClassName?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Viser knapper på hver side av feltet som bruker native stepping.
|
|
16
|
+
* Respekterer `min`, `max` og `step`.
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
stepper?: boolean;
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as
|
|
1
|
+
import{jsxs as e,jsx as a}from"react/jsx-runtime";import{forwardRef as t,useState as r,useRef as s,useEffect as o}from"react";import{getCounterValue as l}from"./counter.js";const n=t((t,n)=>{const{autoExpand:i,counter:u,defaultValue:c,onBlur:d,onFocus:h,rows:f=7,placeholder:x=" ",startOpen:p,style:g,value:m,"aria-invalid":v,onChange:j,...y}=t,_=u?.strategy??"characters",k=typeof m<"u",[w,N]=r(c),[B,C]=r(!1),V=s(null),A=n||V,E=k?m:w,F=k?{value:m}:{defaultValue:c},R=l(E,_),T=u?.maxLength||0,$=T-R,H=!(!v&&!!!(u&&R>T));o(()=>{const e=A.current;if(e){if(!i)return void(e.style.height="");B||E?(e.style.height="auto",e.style.height=`${e.scrollHeight}px`):e.style.height=""}},[i,A,E,B,R]);return e("div",{className:"jkl-text-area-wrapper","data-invalid":H,"data-has-content":R>0,children:[a("textarea",{"aria-invalid":H,className:`jkl-text-area__text-area jkl-text-area__text-area--${f}-rows`,onBlur:function(e){C(!1),d&&d(e)},onFocus:function(e){C(!0),h&&h(e)},onChange:function(e){k||N(e.target.value),j&&j(e)},ref:A,style:{...g,...{overflowX:i?"hidden":void 0}},placeholder:x,...F,...y}),u&&e("div",{className:"jkl-text-area__counter","aria-hidden":"true",children:[e("div",{className:"jkl-text-area__counter-count",children:[R," / ",T]}),!u.hideProgress&&a("div",{className:"jkl-text-area__counter-progress",style:{"--progress-width":(L=$,O=T,L<=0||0===O?0:100*L/O)+"%"}})]})]});var L,O});n.displayName="BaseTextArea";export{n as BaseTextArea};
|
|
2
2
|
//# sourceMappingURL=BaseTextArea.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseTextArea.js","sources":["../../../../src/components/text-area/BaseTextArea.tsx"],"sourcesContent":["import React, {\n type ChangeEvent,\n type FocusEvent,\n forwardRef,\n type RefObject,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { BaseTextAreaProps } from \"./types.js\";\n\nexport const BaseTextArea = forwardRef<HTMLTextAreaElement, BaseTextAreaProps>(\n (props, ref) => {\n const {\n autoExpand,\n counter,\n onBlur,\n onFocus,\n rows = 7,\n placeholder = \" \", // This space intentionally left blank. Denne + rows trengs for å få den ekspanderende effekten.\n startOpen,\n style,\n value,\n \"aria-invalid\": ariaInvalid,\n onChange,\n ...rest\n } = props;\n\n const
|
|
1
|
+
{"version":3,"file":"BaseTextArea.js","sources":["../../../../src/components/text-area/BaseTextArea.tsx"],"sourcesContent":["import React, {\n type ChangeEvent,\n type FocusEvent,\n forwardRef,\n type RefObject,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { getCounterValue } from \"./counter.js\";\nimport type { BaseTextAreaProps } from \"./types.js\";\n\nexport const BaseTextArea = forwardRef<HTMLTextAreaElement, BaseTextAreaProps>(\n (props, ref) => {\n const {\n autoExpand,\n counter,\n defaultValue,\n onBlur,\n onFocus,\n rows = 7,\n placeholder = \" \", // This space intentionally left blank. Denne + rows trengs for å få den ekspanderende effekten.\n startOpen,\n style,\n value,\n \"aria-invalid\": ariaInvalid,\n onChange,\n ...rest\n } = props;\n\n const strategy = counter?.strategy ?? \"characters\";\n const isControlled = typeof value !== \"undefined\";\n\n const [uncontrolledValue, setUncontrolledValue] =\n useState(defaultValue);\n const [textAreaFocused, setTextAreaFocused] = useState(false);\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const textAreaRef =\n (ref as RefObject<HTMLTextAreaElement>) || internalRef;\n\n // Hvis feltet styres utenfra bruker vi `value`, ellers holder vi styr på verdien selv.\n const textAreaValue = isControlled ? value : uncontrolledValue;\n const textAreaValueProps = isControlled ? { value } : { defaultValue };\n\n const counterCurrent = getCounterValue(textAreaValue, strategy);\n const counterTotal: number = counter?.maxLength || 0;\n const progressCurrent: number = counterTotal - counterCurrent;\n const isOverLimit = Boolean(counter && counterCurrent > counterTotal);\n const invalid = Boolean(ariaInvalid || isOverLimit);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: counterCurrent trengs for å lytte på tekstendringer i textarea for auto-expand funksjonalitet\n useEffect(() => {\n const textAreaElement = textAreaRef.current;\n if (textAreaElement) {\n if (!autoExpand) {\n textAreaElement.style.height = \"\";\n return;\n }\n\n if (textAreaFocused || textAreaValue) {\n textAreaElement.style.height = \"auto\"; // Sett til auto før scrollhøyden leses, sånn at redusering av høyde ved sletting av tekst fungerer\n textAreaElement.style.height = `${textAreaElement.scrollHeight}px`;\n } else {\n textAreaElement.style.height = \"\";\n }\n }\n }, [\n autoExpand,\n textAreaRef,\n textAreaValue,\n textAreaFocused,\n counterCurrent,\n ]);\n\n function handleOnFocus(e: FocusEvent<HTMLTextAreaElement>) {\n setTextAreaFocused(true);\n if (onFocus) {\n onFocus(e);\n }\n }\n\n function handleOnBlur(e: FocusEvent<HTMLTextAreaElement>) {\n setTextAreaFocused(false);\n if (onBlur) {\n onBlur(e);\n }\n }\n\n function handleOnChange(e: ChangeEvent<HTMLTextAreaElement>) {\n if (!isControlled) {\n setUncontrolledValue(e.target.value);\n }\n\n if (onChange) {\n onChange(e);\n }\n }\n function calculatePercentage(current: number, total: number): number {\n if (current <= 0) {\n return 0;\n }\n return total === 0 ? 0 : (current * 100) / total;\n }\n\n const overflowStyle = {\n overflowX: autoExpand ? \"hidden\" : undefined, // Must set overflowX hidden for Firefox https://stackoverflow.com/a/22700700\n } as React.CSSProperties;\n\n return (\n <div\n className=\"jkl-text-area-wrapper\"\n data-invalid={invalid}\n data-has-content={counterCurrent > 0}\n >\n <textarea\n aria-invalid={invalid}\n className={`jkl-text-area__text-area jkl-text-area__text-area--${rows}-rows`}\n onBlur={handleOnBlur}\n onFocus={handleOnFocus}\n onChange={handleOnChange}\n ref={textAreaRef}\n style={{ ...style, ...overflowStyle }}\n placeholder={placeholder}\n {...textAreaValueProps}\n {...rest}\n />\n {counter && (\n <div className=\"jkl-text-area__counter\" aria-hidden=\"true\">\n <div className=\"jkl-text-area__counter-count\">\n {counterCurrent} / {counterTotal}\n </div>\n {!counter.hideProgress && (\n <div\n className=\"jkl-text-area__counter-progress\"\n style={{\n [\"--progress-width\" as string]: `${calculatePercentage(\n progressCurrent,\n counterTotal,\n )}%`,\n }}\n />\n )}\n </div>\n )}\n </div>\n );\n },\n);\nBaseTextArea.displayName = \"BaseTextArea\";\n"],"names":["BaseTextArea","forwardRef","props","ref","autoExpand","counter","defaultValue","onBlur","onFocus","rows","placeholder","startOpen","style","value","ariaInvalid","onChange","rest","strategy","isControlled","uncontrolledValue","setUncontrolledValue","useState","textAreaFocused","setTextAreaFocused","internalRef","useRef","textAreaRef","textAreaValue","textAreaValueProps","counterCurrent","getCounterValue","counterTotal","maxLength","progressCurrent","invalid","useEffect","textAreaElement","current","height","scrollHeight","jsxs","className","children","jsx","e","target","overflowX","hideProgress","total","displayName"],"mappings":"6KAYO,MAAMA,EAAeC,EACxB,CAACC,EAAOC,KACJ,MACIC,WAAAA,EACAC,QAAAA,EACAC,aAAAA,EACAC,OAAAA,EACAC,QAAAA,EACAC,KAAAA,EAAO,EACPC,YAAAA,EAAc,IACdC,UAAAA,EACAC,MAAAA,EACAC,MAAAA,EACA,eAAgBC,EAChBC,SAAAA,KACGC,GACHd,EAEEe,EAAWZ,GAASY,UAAY,aAChCC,SAAsBL,EAAU,KAE/BM,EAAmBC,GACtBC,EAASf,IACNgB,EAAiBC,GAAsBF,GAAS,GACjDG,EAAcC,EAA4B,MAC1CC,EACDvB,GAA0CqB,EAGzCG,EAAgBT,EAAeL,EAAQM,EACvCS,EAAqBV,EAAe,CAAEL,MAAAA,GAAU,CAAEP,aAAAA,GAElDuB,EAAiBC,EAAgBH,EAAeV,GAChDc,EAAuB1B,GAAS2B,WAAa,EAC7CC,EAA0BF,EAAeF,EAEzCK,KAAkBpB,OADIT,GAAWwB,EAAiBE,IAIxDI,EAAU,KACN,MAAMC,EAAkBV,EAAYW,QACpC,GAAID,EAAiB,CACjB,IAAKhC,EAED,YADAgC,EAAgBxB,MAAM0B,OAAS,IAI/BhB,GAAmBK,GACnBS,EAAgBxB,MAAM0B,OAAS,OAC/BF,EAAgBxB,MAAM0B,OAAS,GAAGF,EAAgBG,kBAElDH,EAAgBxB,MAAM0B,OAAS,EAEvC,GACD,CACClC,EACAsB,EACAC,EACAL,EACAO,IAqCJ,OACIW,EAAC,MAAA,CACGC,UAAU,wBACV,eAAcP,EACd,mBAAkBL,EAAiB,EAEnCa,SAAA,CAAAC,EAAC,WAAA,CACG,eAAcT,EACdO,UAAW,sDAAsDhC,SACjEF,OApCZ,SAAsBqC,GAClBrB,GAAmB,GACfhB,GACAA,EAAOqC,EAEf,EAgCYpC,QA5CZ,SAAuBoC,GACnBrB,GAAmB,GACff,GACAA,EAAQoC,EAEhB,EAwCY7B,SA/BZ,SAAwB6B,GACf1B,GACDE,EAAqBwB,EAAEC,OAAOhC,OAG9BE,GACAA,EAAS6B,EAEjB,EAwBYzC,IAAKuB,EACLd,MAAO,IAAKA,KAjBF,CAClBkC,UAAW1C,EAAa,cAAW,IAiB3BM,YAAAA,KACIkB,KACAZ,IAEPX,GACGmC,EAAC,MAAA,CAAIC,UAAU,yBAAyB,cAAY,OAChDC,SAAA,CAAAF,EAAC,MAAA,CAAIC,UAAU,+BACVC,SAAA,CAAAb,EAAe,MAAcE,MAEhC1B,EAAQ0C,cACNJ,EAAC,MAAA,CACGF,UAAU,kCACV7B,MAAO,CACF,oBAtCAyB,EAuCGJ,EAvCce,EAwCdjB,EAvCxBM,GAAW,GAGE,IAAVW,EAFI,EAEyB,IAAVX,EAAiBW,GAkCa,aAtC5D,IAA6BX,EAAiBW,IAmDtDhD,EAAaiD,YAAc"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter.js","sources":["../../../../src/components/text-area/counter.ts"],"sourcesContent":["import type { CounterStrategy } from \"./types.js\";\n\nconst textEncoder = new TextEncoder();\n\nexport function getCounterValue(\n value: string | number | readonly string[] | undefined,\n strategy: CounterStrategy = \"characters\",\n): number {\n if (typeof value === \"undefined\") {\n return 0;\n }\n\n const normalizedValue =\n typeof value === \"string\"\n ? value\n : Array.isArray(value)\n ? value.join(\"\")\n : String(value);\n\n if (strategy === \"bytes\") {\n return textEncoder.encode(normalizedValue).length;\n }\n\n return normalizedValue.length;\n}\n"],"names":["textEncoder","TextEncoder","getCounterValue","value","strategy","normalizedValue","Array","isArray","join","String","encode","length"],"mappings":"AAEA,MAAMA,EAAc,IAAIC,YAEjB,SAASC,EACZC,EACAC,EAA4B,cAE5B,UAAWD,EAAU,IACjB,OAAO,EAGX,MAAME,EACe,iBAAVF,EACDA,EACAG,MAAMC,QAAQJ,GACZA,EAAMK,KAAK,IACXC,OAAON,GAEnB,MAAiB,UAAbC,EACOJ,EAAYU,OAAOL,GAAiBM,OAGxCN,EAAgBM,MAC3B"}
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { TextareaHTMLAttributes } from 'react';
|
|
2
2
|
import { InputGroupProps } from '../input-group/types.js';
|
|
3
|
+
export type CounterStrategy = "characters" | "bytes";
|
|
3
4
|
export type Counter = {
|
|
4
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Maksverdi for telleren.
|
|
7
|
+
*
|
|
8
|
+
* Enheten avhenger av `strategy`:
|
|
9
|
+
* - `"characters"`: antall tegn
|
|
10
|
+
* - `"bytes"`: antall UTF-8-bytes
|
|
11
|
+
*/
|
|
5
12
|
maxLength: number;
|
|
13
|
+
/**
|
|
14
|
+
* Bestemmer hva telleren måler.
|
|
15
|
+
*
|
|
16
|
+
* - "characters" teller tekst på samme måte som i dag og er standard
|
|
17
|
+
* - "bytes" teller antall UTF-8-bytes, for usecaser der backend eller API
|
|
18
|
+
* håndhever en bytegrense
|
|
19
|
+
*
|
|
20
|
+
* Unngå å kombinere `strategy="bytes"` med native `maxLength` på
|
|
21
|
+
* `<textarea>`, siden nettleseren fortsatt håndhever `maxLength` som tegn.
|
|
22
|
+
*
|
|
23
|
+
* @default "characters"
|
|
24
|
+
*/
|
|
25
|
+
strategy?: CounterStrategy;
|
|
6
26
|
/**
|
|
7
27
|
* Med teller vises en progress-bar i bunnen av tekstfeltet som krymper
|
|
8
28
|
* ned fra 100% (null tegn skrevet) til 0% (maks antall tegn skrevet).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fremtind/jokul",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -400,6 +400,17 @@
|
|
|
400
400
|
"default": "./build/cjs/components/nav-link/index.cjs"
|
|
401
401
|
}
|
|
402
402
|
},
|
|
403
|
+
"./styles/components/number-input": "./styles/components/number-input/_index.scss",
|
|
404
|
+
"./number-input": {
|
|
405
|
+
"import": {
|
|
406
|
+
"types": "./build/es/components/number-input/index.d.ts",
|
|
407
|
+
"default": "./build/es/components/number-input/index.js"
|
|
408
|
+
},
|
|
409
|
+
"require": {
|
|
410
|
+
"types": "./build/cjs/components/number-input/index.d.cts",
|
|
411
|
+
"default": "./build/cjs/components/number-input/index.cjs"
|
|
412
|
+
}
|
|
413
|
+
},
|
|
403
414
|
"./styles/components/pagination": "./styles/components/pagination/_index.scss",
|
|
404
415
|
"./pagination": {
|
|
405
416
|
"import": {
|
|
@@ -712,6 +723,7 @@
|
|
|
712
723
|
"compile:scripts": "vite build --config vite.build.config.mjs",
|
|
713
724
|
"test": "vitest --config vite.test.config.mjs",
|
|
714
725
|
"figma:test": "figma connect publish --dry-run",
|
|
726
|
+
"figma:test:ci": "figma connect publish --dry-run --exit-on-unreadable-files --skip-update-check",
|
|
715
727
|
"figma:publish": "figma connect publish"
|
|
716
728
|
}
|
|
717
729
|
}
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
.jkl-countdown__tracker {
|
|
29
|
-
animation: jkl-downcount-
|
|
29
|
+
animation: jkl-downcount-u48auaz var(--duration) linear forwards;
|
|
30
30
|
animation-play-state: var(--play-state, running);
|
|
31
31
|
}
|
|
32
|
-
@keyframes jkl-downcount-
|
|
32
|
+
@keyframes jkl-downcount-u48auaz {
|
|
33
33
|
from {
|
|
34
34
|
width: 100%;
|
|
35
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer jokul.components{.jkl-countdown{--track-color:var(--jkl-color-border-separator);--bar-color:var(--jkl-color-border-input-focus);--bar-height:0.25rem;background-color:var(--track-color);border-radius:6.25rem;height:var(--bar-height);overflow:hidden;width:100%}.jkl-countdown__tracker{background-color:var(--bar-color);display:block;height:var(--bar-height)}@media screen and (forced-colors:active){.jkl-countdown{background-color:Canvas}.jkl-countdown__tracker{background-color:CanvasText}}.jkl-countdown__tracker{animation:jkl-downcount-
|
|
1
|
+
@layer jokul.components{.jkl-countdown{--track-color:var(--jkl-color-border-separator);--bar-color:var(--jkl-color-border-input-focus);--bar-height:0.25rem;background-color:var(--track-color);border-radius:6.25rem;height:var(--bar-height);overflow:hidden;width:100%}.jkl-countdown__tracker{background-color:var(--bar-color);display:block;height:var(--bar-height)}@media screen and (forced-colors:active){.jkl-countdown{background-color:Canvas}.jkl-countdown__tracker{background-color:CanvasText}}.jkl-countdown__tracker{animation:jkl-downcount-u48auaz var(--duration) linear forwards;animation-play-state:var(--play-state,running)}@keyframes jkl-downcount-u48auaz{0%{width:100%}to{width:0}}}
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
--jkl-icon-size: 1.2em;
|
|
25
25
|
}
|
|
26
26
|
.jkl-feedback__fade-in {
|
|
27
|
-
animation: jkl-show-
|
|
27
|
+
animation: jkl-show-ugq1gt2 0.25s ease-out;
|
|
28
28
|
}
|
|
29
29
|
.jkl-feedback__buttons {
|
|
30
30
|
display: flex;
|
|
31
31
|
}
|
|
32
|
-
@keyframes jkl-show-
|
|
32
|
+
@keyframes jkl-show-ugq1gt2 {
|
|
33
33
|
from {
|
|
34
34
|
transform: translate3d(0, 0.5rem, 0);
|
|
35
35
|
opacity: 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer jokul.components{.jkl-feedback{max-width:34.375rem}.jkl-feedback__submit-wrapper{transition-duration:.25s;transition-property:height;transition-timing-function:ease;width:100%}.jkl-feedback__submit-wrapper--hidden{display:none}.jkl-feedback__step-counter{color:var(--jkl-color-text-subdued);font-size:var(--jkl-font-size-2);font-weight:400;line-height:var(--jkl-line-height-relaxed);margin-bottom:var(--jkl-unit-20);--jkl-icon-weight:300;--jkl-icon-size:1.2em}.jkl-feedback__fade-in{animation:jkl-show-
|
|
1
|
+
@layer jokul.components{.jkl-feedback{max-width:34.375rem}.jkl-feedback__submit-wrapper{transition-duration:.25s;transition-property:height;transition-timing-function:ease;width:100%}.jkl-feedback__submit-wrapper--hidden{display:none}.jkl-feedback__step-counter{color:var(--jkl-color-text-subdued);font-size:var(--jkl-font-size-2);font-weight:400;line-height:var(--jkl-line-height-relaxed);margin-bottom:var(--jkl-unit-20);--jkl-icon-weight:300;--jkl-icon-size:1.2em}.jkl-feedback__fade-in{animation:jkl-show-ugq1gt2 .25s ease-out}.jkl-feedback__buttons{display:flex}@keyframes jkl-show-ugq1gt2{0%{opacity:0;transform:translate3d(0,.5rem,0)}}.jkl-feedback-smileys{display:flex;flex-wrap:nowrap;gap:.75rem;justify-content:space-between;margin-top:var(--jkl-unit-10);max-width:22.5rem;width:100%}.jkl-feedback-smiley-option{color:var(--jkl-color-text-subdued);cursor:pointer;display:inline-block;height:2.5rem;position:relative;transform:translateZ(0);transition-duration:.15s;transition-property:transform,color;transition-timing-function:ease;width:2.5rem}@media screen and (forced-colors:active){.jkl-feedback-smiley-option,.jkl-feedback-smiley-option path,.jkl-feedback-smiley-option svg{fill:ButtonText;stroke:ButtonFace}}.jkl-feedback-smiley-option:after,.jkl-feedback-smiley-option:before{border-radius:50%;content:"";opacity:0;position:absolute;transition-duration:.15s;transition-property:opacity;transition-timing-function:ease}.jkl-feedback-smiley-option:before{box-shadow:0 .125rem 1.875rem rgba(0,0,0,.1);inset:0}.jkl-feedback-smiley-option:hover{color:var(--jkl-color-text-default)}input:checked+.jkl-feedback-smiley-option{color:var(--jkl-color-text-default);transform:translate3d(0,-20%,0)}input:checked+.jkl-feedback-smiley-option:before{opacity:1}input:focus-visible+.jkl-feedback-smiley-option{border-radius:var(--jkl-border-radius-full);outline:3px solid var(--jkl-color-border-action);outline-offset:3px}}
|
|
@@ -348,22 +348,22 @@
|
|
|
348
348
|
animation: 2500ms linear infinite;
|
|
349
349
|
}
|
|
350
350
|
.jkl-loader__dot--left {
|
|
351
|
-
animation-name: jkl-loader-left-spin-
|
|
351
|
+
animation-name: jkl-loader-left-spin-u3xniv8;
|
|
352
352
|
margin-right: calc(var(--jkl-loader-spacing) * 0.9);
|
|
353
353
|
}
|
|
354
354
|
.jkl-loader__dot--middle {
|
|
355
|
-
animation-name: jkl-loader-middle-spin-
|
|
355
|
+
animation-name: jkl-loader-middle-spin-u3xniw6;
|
|
356
356
|
margin-right: var(--jkl-loader-spacing);
|
|
357
357
|
}
|
|
358
358
|
.jkl-loader__dot--right {
|
|
359
|
-
animation-name: jkl-loader-right-spin-
|
|
359
|
+
animation-name: jkl-loader-right-spin-u3xnix3;
|
|
360
360
|
}
|
|
361
361
|
@media screen and (forced-colors: active) {
|
|
362
362
|
.jkl-loader__dot {
|
|
363
363
|
background-color: CanvasText;
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
|
-
@keyframes jkl-loader-left-spin-
|
|
366
|
+
@keyframes jkl-loader-left-spin-u3xniv8 {
|
|
367
367
|
0% {
|
|
368
368
|
transform: rotate(0) scale(0);
|
|
369
369
|
}
|
|
@@ -377,7 +377,7 @@
|
|
|
377
377
|
transform: rotate(180deg) scale(0);
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
|
-
@keyframes jkl-loader-middle-spin-
|
|
380
|
+
@keyframes jkl-loader-middle-spin-u3xniw6 {
|
|
381
381
|
0% {
|
|
382
382
|
transform: rotate(20deg) scale(0);
|
|
383
383
|
}
|
|
@@ -394,7 +394,7 @@
|
|
|
394
394
|
transform: rotate(200deg) scale(0);
|
|
395
395
|
}
|
|
396
396
|
}
|
|
397
|
-
@keyframes jkl-loader-right-spin-
|
|
397
|
+
@keyframes jkl-loader-right-spin-u3xnix3 {
|
|
398
398
|
0% {
|
|
399
399
|
transform: rotate(40deg) scale(0);
|
|
400
400
|
}
|
|
@@ -434,7 +434,7 @@
|
|
|
434
434
|
@media screen and (forced-colors: active) {
|
|
435
435
|
.jkl-skeleton-element {
|
|
436
436
|
border: 1px solid CanvasText;
|
|
437
|
-
animation: 2s ease infinite jkl-blink-
|
|
437
|
+
animation: 2s ease infinite jkl-blink-u3xnixw;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
.jkl-skeleton-input {
|
|
@@ -482,10 +482,10 @@
|
|
|
482
482
|
}
|
|
483
483
|
@media screen and (forced-colors: active) {
|
|
484
484
|
.jkl-skeleton-table {
|
|
485
|
-
animation: 2s ease-in-out infinite jkl-blink-
|
|
485
|
+
animation: 2s ease-in-out infinite jkl-blink-u3xnixw;
|
|
486
486
|
}
|
|
487
487
|
}
|
|
488
|
-
@keyframes jkl-blink-
|
|
488
|
+
@keyframes jkl-blink-u3xnixw {
|
|
489
489
|
0% {
|
|
490
490
|
opacity: 1;
|
|
491
491
|
}
|