@reykjavik/hanna-react 0.10.119 → 0.10.121

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.
@@ -37,6 +37,8 @@ export type AutosuggestSearchProps<T extends string | object> = {
37
37
  isHighlighted: boolean;
38
38
  }) => JSX.Element | string;
39
39
  itemActionIcon?: 'search' | 'go';
40
+ inputValue?: string;
41
+ defaultInputValue?: string;
40
42
  InputComponent?: (props: SiteSearchInputProps & SearchInputProps) => JSX.Element;
41
43
  renderInputField?: (inputProps: RenderInputComponentProps, texts: AutosuggestSearchI18n) => JSX.Element;
42
44
  texts?: AutosuggestSearchI18n;
@@ -7,6 +7,7 @@ const react_autosuggest_1 = tslib_1.__importDefault(require("react-autosuggest")
7
7
  const classUtils_1 = require("@hugsmidjan/qj/classUtils");
8
8
  const i18n_1 = require("@reykjavik/hanna-utils/i18n");
9
9
  const SearchInput_js_1 = tslib_1.__importDefault(require("./SearchInput.js"));
10
+ const utils_js_1 = require("./utils.js");
10
11
  exports.defaultAutosuggestSearchTexts = {
11
12
  is: {
12
13
  label: 'Leit á vefnum',
@@ -38,7 +39,7 @@ const AutosuggestSearch = (props) => {
38
39
  : '', renderSuggestion = (opt) => typeof opt === 'object' && 'label' in opt && opt.label != null
39
40
  ? opt.label.toString()
40
41
  : getOptionValue(opt), InputComponent = SearchInput_js_1.default, renderInputField, wrapperProps, } = props;
41
- const [value, setValue] = (0, react_1.useState)('');
42
+ const [inputValue, setInputValue] = (0, utils_js_1.useMixedControlState)(props, 'inputValue', '');
42
43
  const inputRef = (0, react_1.useRef)(null);
43
44
  const txt = (0, i18n_1.getTexts)(props, exports.defaultAutosuggestSearchTexts);
44
45
  const showEmptyMessage = !options.length && emptyMessage;
@@ -50,8 +51,11 @@ const AutosuggestSearch = (props) => {
50
51
  suggestionsList: (0, classUtils_1.modifiedClass)('AutosuggestSearch__list', itemActionIcon && `action--${itemActionIcon}`),
51
52
  suggestion: 'AutosuggestSearch__item',
52
53
  suggestionHighlighted: 'AutosuggestSearch__item--highlighted',
53
- }, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ({ value }) => onInput(value), getSuggestionValue: showEmptyMessage
54
- ? () => value // Return the input value in case the user uses the up/down keys to select the hidden empty message
54
+ }, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ( /* { value } */) => {
55
+ // weirdly required prop, but we don't need to do anything here
56
+ // as we run onInput on input change below.
57
+ }, getSuggestionValue: showEmptyMessage
58
+ ? () => inputValue // Return the input value in case the user uses the up/down keys to select the hidden empty message
55
59
  : getOptionValue, onSuggestionSelected: (event, data) => {
56
60
  if (showEmptyMessage) {
57
61
  event.preventDefault();
@@ -71,16 +75,17 @@ const AutosuggestSearch = (props) => {
71
75
  return (react_1.default.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
72
76
  }, inputProps: {
73
77
  ref: inputRef,
74
- value: value,
78
+ value: inputValue,
75
79
  onChange: (_, { newValue }) => {
76
- setValue(newValue);
80
+ onInput(newValue);
81
+ setInputValue(newValue);
77
82
  },
78
83
  }, renderInputComponent: renderInputField
79
84
  ? (inputProps) => renderInputField(inputProps, txt)
80
85
  : (inputProps) => {
81
86
  /* prettier-ignore */
82
- const { className, type, disabled, readOnly, required, children, ref } = inputProps, siteSearchProps = tslib_1.__rest(inputProps, ["className", "type", "disabled", "readOnly", "required", "children", "ref"]);
83
- return (react_1.default.createElement(InputComponent, Object.assign({ lang: props.lang }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, onSubmit: onSubmit && (() => onSubmit(value)), onButtonClick: onButtonClick && (() => onButtonClick(value)) })));
87
+ const { className, type, disabled, readOnly, required, children, ref, defaultValue } = inputProps, siteSearchProps = tslib_1.__rest(inputProps, ["className", "type", "disabled", "readOnly", "required", "children", "ref", "defaultValue"]);
88
+ return (react_1.default.createElement(InputComponent, Object.assign({ lang: props.lang, defaultValue: defaultValue }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, onSubmit: onSubmit && (() => onSubmit(inputValue)), onButtonClick: onButtonClick && (() => onButtonClick(inputValue)) })));
84
89
  } }));
85
90
  };
86
91
  exports.AutosuggestSearch = AutosuggestSearch;
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@
4
4
 
5
5
  - ... <!-- Add new lines here. -->
6
6
 
7
+ ## 0.10.121
8
+
9
+ _2024-03-14_
10
+
11
+ - fix: Translate `FormField` and `Checkbox` required label to 'en' and 'pl'
12
+ - fix: `DatePicker` only partially reflected the current `DEFAULT_LANG`
13
+
14
+ ## 0.10.120
15
+
16
+ _2024-03-06_
17
+
18
+ - feat: Add props `inputValue`, `defaultInputValue` to `AutosuggestSearch`
19
+ - fix: `AutosuggestSearch` not calling `onInput` when input is emptied
20
+
7
21
  ## 0.10.119
8
22
 
9
23
  _2024-02-29_
package/Datepicker.js CHANGED
@@ -153,7 +153,7 @@ const Datepicker = (props) => {
153
153
  return elm;
154
154
  }) }, addFocusProps()),
155
155
  isoMode && (react_1.default.createElement("input", { type: "hidden", name: name, value: value === null || value === void 0 ? void 0 : value.toISOString().slice(0, 10) })),
156
- react_1.default.createElement(ReactDatepicker_js_1.ReactDatePicker, Object.assign({ id: domid, required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: isoMode ? undefined : name, locale: lang, dateFormat: normalizedDateFormats, onChange: (date) => {
156
+ react_1.default.createElement(ReactDatepicker_js_1.ReactDatePicker, Object.assign({ id: domid, required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: isoMode ? undefined : name, locale: lang || i18n_1.DEFAULT_LANG, dateFormat: normalizedDateFormats, onChange: (date) => {
157
157
  date = date || undefined;
158
158
  setValue(date);
159
159
  onChange && onChange(date);
package/FormField.js CHANGED
@@ -4,6 +4,7 @@ exports.groupFormFieldWrapperProps = exports.getFormFieldWrapperProps = exports.
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importStar(require("react"));
6
6
  const classUtils_1 = require("@hugsmidjan/qj/classUtils");
7
+ const i18n_1 = require("@reykjavik/hanna-utils/i18n");
7
8
  const env_js_1 = require("./utils/env.js");
8
9
  const useDomid_js_1 = require("./utils/useDomid.js");
9
10
  const utils_js_1 = require("./utils.js");
@@ -14,6 +15,12 @@ const inputClassNames = {
14
15
  control: 'FormField__control',
15
16
  };
16
17
  // ---------------------------------------------------------------------------
18
+ const defaultReqText = {
19
+ is: 'Þarf að fylla út',
20
+ en: 'Required',
21
+ pl: 'Wymagane',
22
+ };
23
+ // ---------------------------------------------------------------------------
17
24
  // eslint-disable-next-line complexity
18
25
  const FormField = (props) => {
19
26
  const { extraClassName, className, small, group, LabelTag = group ? 'h4' : undefined, label, assistText, hideLabel, empty, filled, readOnly, disabled, invalid, errorMessage, required, reqText, // TODO: i18n
@@ -57,7 +64,7 @@ const FormField = (props) => {
57
64
  const labelId = LabelTag ? `label:${domid}` : undefined;
58
65
  const reqStar = required && reqText !== false && (react_1.default.createElement("abbr", { className: "FormField__label__reqstar",
59
66
  // FIXME: add mo-better i18n thinking
60
- title: `${reqText || 'Þarf að fylla út'}: ` }, "*"));
67
+ title: `${reqText || defaultReqText[i18n_1.DEFAULT_LANG]}: ` }, "*"));
61
68
  const inputProps = {
62
69
  id: domid,
63
70
  disabled: disabled,
package/SearchInput.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { RefObject } from 'react';
2
2
  import { FormFieldWrappingProps } from './FormField.js';
3
- type InputElmProps = Omit<JSX.IntrinsicElements['input'], 'className' | 'type' | 'disabled' | 'readOnly' | 'required' | 'onSubmit' | 'ref' | 'value'> & {
3
+ type InputElmProps = Omit<JSX.IntrinsicElements['input'], 'className' | 'type' | 'disabled' | 'readOnly' | 'required' | 'onSubmit' | 'ref' | 'value' | 'defaultValue'> & {
4
4
  value?: string;
5
+ defaultValue?: string;
5
6
  };
6
7
  export type SearchInputProps = FormFieldWrappingProps & {
7
8
  small?: boolean;
@@ -4,12 +4,13 @@ export type TogglerInputProps = {
4
4
  label: string | JSX.Element;
5
5
  children?: never;
6
6
  invalid?: boolean;
7
- /** Hidden label prefix text to indicate that the field is required.
7
+ /**
8
+ * Hidden label prefix text to indicate that the field is required.
8
9
  *
9
10
  * If your field is required but should not say so in its label
10
11
  * then set this prop to `false`
11
12
  *
12
- * Default: `"Þarf að fylla út"`
13
+ * Default: `"Þarf að haka í" / "Must be checked" / "Należy sprawdzić"`.
13
14
  * */
14
15
  reqText?: string | false;
15
16
  hideLabel?: boolean;
@@ -4,7 +4,13 @@ exports.TogglerInput = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const classUtils_1 = require("@hugsmidjan/qj/classUtils");
7
+ const i18n_js_1 = require("@reykjavik/hanna-utils/i18n.js");
7
8
  const useDomid_js_1 = require("../utils/useDomid.js");
9
+ const defaultReqText = {
10
+ is: 'Þarf að haka í',
11
+ en: 'Must be checked',
12
+ pl: 'Należy sprawdzić',
13
+ };
8
14
  // eslint-disable-next-line complexity
9
15
  const TogglerInput = (props) => {
10
16
  const { bem, modifier, className, label, hideLabel, invalid, errorMessage, Wrapper = 'div', required, reqText, type, id, innerWrap, wrapperProps, inputProps } = props, restInputProps = tslib_1.__rest(props, ["bem", "modifier", "className", "label", "hideLabel", "invalid", "errorMessage", "Wrapper", "required", "reqText", "type", "id", "innerWrap", "wrapperProps", "inputProps"]);
@@ -12,7 +18,7 @@ const TogglerInput = (props) => {
12
18
  const errorId = errorMessage && `error${domid}`;
13
19
  const reqStar = required && reqText !== false && (react_1.default.createElement("abbr", { className: `${bem}__label__reqstar`,
14
20
  // FIXME: add mo-better i18n thinking
15
- title: `${reqText || 'Þarf að haka í'}: ` }, "*"));
21
+ title: `${reqText || defaultReqText[i18n_js_1.DEFAULT_LANG]}: ` }, "*"));
16
22
  const readOnly = restInputProps.readOnly || (inputProps || {}).readOnly;
17
23
  const labelContent = (react_1.default.createElement(react_1.default.Fragment, null,
18
24
  ' ',
@@ -37,6 +37,8 @@ export type AutosuggestSearchProps<T extends string | object> = {
37
37
  isHighlighted: boolean;
38
38
  }) => JSX.Element | string;
39
39
  itemActionIcon?: 'search' | 'go';
40
+ inputValue?: string;
41
+ defaultInputValue?: string;
40
42
  InputComponent?: (props: SiteSearchInputProps & SearchInputProps) => JSX.Element;
41
43
  renderInputField?: (inputProps: RenderInputComponentProps, texts: AutosuggestSearchI18n) => JSX.Element;
42
44
  texts?: AutosuggestSearchI18n;
@@ -1,9 +1,10 @@
1
1
  import { __rest } from "tslib";
2
- import React, { useRef, useState } from 'react';
2
+ import React, { useRef } from 'react';
3
3
  import Autosuggest from 'react-autosuggest';
4
4
  import { modifiedClass } from '@hugsmidjan/qj/classUtils';
5
5
  import { getTexts } from '@reykjavik/hanna-utils/i18n';
6
6
  import SearchInput from './SearchInput.js';
7
+ import { useMixedControlState } from './utils.js';
7
8
  export const defaultAutosuggestSearchTexts = {
8
9
  is: {
9
10
  label: 'Leit á vefnum',
@@ -35,7 +36,7 @@ export const AutosuggestSearch = (props) => {
35
36
  : '', renderSuggestion = (opt) => typeof opt === 'object' && 'label' in opt && opt.label != null
36
37
  ? opt.label.toString()
37
38
  : getOptionValue(opt), InputComponent = SearchInput, renderInputField, wrapperProps, } = props;
38
- const [value, setValue] = useState('');
39
+ const [inputValue, setInputValue] = useMixedControlState(props, 'inputValue', '');
39
40
  const inputRef = useRef(null);
40
41
  const txt = getTexts(props, defaultAutosuggestSearchTexts);
41
42
  const showEmptyMessage = !options.length && emptyMessage;
@@ -47,8 +48,11 @@ export const AutosuggestSearch = (props) => {
47
48
  suggestionsList: modifiedClass('AutosuggestSearch__list', itemActionIcon && `action--${itemActionIcon}`),
48
49
  suggestion: 'AutosuggestSearch__item',
49
50
  suggestionHighlighted: 'AutosuggestSearch__item--highlighted',
50
- }, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ({ value }) => onInput(value), getSuggestionValue: showEmptyMessage
51
- ? () => value // Return the input value in case the user uses the up/down keys to select the hidden empty message
51
+ }, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ( /* { value } */) => {
52
+ // weirdly required prop, but we don't need to do anything here
53
+ // as we run onInput on input change below.
54
+ }, getSuggestionValue: showEmptyMessage
55
+ ? () => inputValue // Return the input value in case the user uses the up/down keys to select the hidden empty message
52
56
  : getOptionValue, onSuggestionSelected: (event, data) => {
53
57
  if (showEmptyMessage) {
54
58
  event.preventDefault();
@@ -68,15 +72,16 @@ export const AutosuggestSearch = (props) => {
68
72
  return (React.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
69
73
  }, inputProps: {
70
74
  ref: inputRef,
71
- value: value,
75
+ value: inputValue,
72
76
  onChange: (_, { newValue }) => {
73
- setValue(newValue);
77
+ onInput(newValue);
78
+ setInputValue(newValue);
74
79
  },
75
80
  }, renderInputComponent: renderInputField
76
81
  ? (inputProps) => renderInputField(inputProps, txt)
77
82
  : (inputProps) => {
78
83
  /* prettier-ignore */
79
- const { className, type, disabled, readOnly, required, children, ref } = inputProps, siteSearchProps = __rest(inputProps, ["className", "type", "disabled", "readOnly", "required", "children", "ref"]);
80
- return (React.createElement(InputComponent, Object.assign({ lang: props.lang }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, onSubmit: onSubmit && (() => onSubmit(value)), onButtonClick: onButtonClick && (() => onButtonClick(value)) })));
84
+ const { className, type, disabled, readOnly, required, children, ref, defaultValue } = inputProps, siteSearchProps = __rest(inputProps, ["className", "type", "disabled", "readOnly", "required", "children", "ref", "defaultValue"]);
85
+ return (React.createElement(InputComponent, Object.assign({ lang: props.lang, defaultValue: defaultValue }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, onSubmit: onSubmit && (() => onSubmit(inputValue)), onButtonClick: onButtonClick && (() => onButtonClick(inputValue)) })));
81
86
  } }));
82
87
  };
package/esm/Datepicker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import React, { useMemo } from 'react';
2
- import { getTexts } from '@reykjavik/hanna-utils/i18n';
2
+ import { DEFAULT_LANG, getTexts, } from '@reykjavik/hanna-utils/i18n';
3
3
  // For more info on localization see: https://stackoverflow.com/questions/54399084/change-locale-in-react-datepicker/58306958#58306958
4
4
  import is from 'date-fns/locale/is/index.js';
5
5
  import pl from 'date-fns/locale/pl/index.js';
@@ -148,7 +148,7 @@ export const Datepicker = (props) => {
148
148
  return elm;
149
149
  }) }, addFocusProps()),
150
150
  isoMode && (React.createElement("input", { type: "hidden", name: name, value: value === null || value === void 0 ? void 0 : value.toISOString().slice(0, 10) })),
151
- React.createElement(ReactDatePicker, Object.assign({ id: domid, required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: isoMode ? undefined : name, locale: lang, dateFormat: normalizedDateFormats, onChange: (date) => {
151
+ React.createElement(ReactDatePicker, Object.assign({ id: domid, required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: isoMode ? undefined : name, locale: lang || DEFAULT_LANG, dateFormat: normalizedDateFormats, onChange: (date) => {
152
152
  date = date || undefined;
153
153
  setValue(date);
154
154
  onChange && onChange(date);
package/esm/FormField.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { __rest } from "tslib";
2
2
  import React, { useCallback, useState } from 'react';
3
3
  import { modifiedClass } from '@hugsmidjan/qj/classUtils';
4
+ import { DEFAULT_LANG } from '@reykjavik/hanna-utils/i18n';
4
5
  import { isPreact } from './utils/env.js';
5
6
  import { useDomid } from './utils/useDomid.js';
6
7
  import { useIsBrowserSide } from './utils.js';
@@ -11,6 +12,12 @@ const inputClassNames = {
11
12
  control: 'FormField__control',
12
13
  };
13
14
  // ---------------------------------------------------------------------------
15
+ const defaultReqText = {
16
+ is: 'Þarf að fylla út',
17
+ en: 'Required',
18
+ pl: 'Wymagane',
19
+ };
20
+ // ---------------------------------------------------------------------------
14
21
  // eslint-disable-next-line complexity
15
22
  export const FormField = (props) => {
16
23
  const { extraClassName, className, small, group, LabelTag = group ? 'h4' : undefined, label, assistText, hideLabel, empty, filled, readOnly, disabled, invalid, errorMessage, required, reqText, // TODO: i18n
@@ -54,7 +61,7 @@ export const FormField = (props) => {
54
61
  const labelId = LabelTag ? `label:${domid}` : undefined;
55
62
  const reqStar = required && reqText !== false && (React.createElement("abbr", { className: "FormField__label__reqstar",
56
63
  // FIXME: add mo-better i18n thinking
57
- title: `${reqText || 'Þarf að fylla út'}: ` }, "*"));
64
+ title: `${reqText || defaultReqText[DEFAULT_LANG]}: ` }, "*"));
58
65
  const inputProps = {
59
66
  id: domid,
60
67
  disabled: disabled,
@@ -1,7 +1,8 @@
1
1
  import { RefObject } from 'react';
2
2
  import { FormFieldWrappingProps } from './FormField.js';
3
- type InputElmProps = Omit<JSX.IntrinsicElements['input'], 'className' | 'type' | 'disabled' | 'readOnly' | 'required' | 'onSubmit' | 'ref' | 'value'> & {
3
+ type InputElmProps = Omit<JSX.IntrinsicElements['input'], 'className' | 'type' | 'disabled' | 'readOnly' | 'required' | 'onSubmit' | 'ref' | 'value' | 'defaultValue'> & {
4
4
  value?: string;
5
+ defaultValue?: string;
5
6
  };
6
7
  export type SearchInputProps = FormFieldWrappingProps & {
7
8
  small?: boolean;
@@ -4,12 +4,13 @@ export type TogglerInputProps = {
4
4
  label: string | JSX.Element;
5
5
  children?: never;
6
6
  invalid?: boolean;
7
- /** Hidden label prefix text to indicate that the field is required.
7
+ /**
8
+ * Hidden label prefix text to indicate that the field is required.
8
9
  *
9
10
  * If your field is required but should not say so in its label
10
11
  * then set this prop to `false`
11
12
  *
12
- * Default: `"Þarf að fylla út"`
13
+ * Default: `"Þarf að haka í" / "Must be checked" / "Należy sprawdzić"`.
13
14
  * */
14
15
  reqText?: string | false;
15
16
  hideLabel?: boolean;
@@ -1,7 +1,13 @@
1
1
  import { __rest } from "tslib";
2
2
  import React from 'react';
3
3
  import { modifiedClass } from '@hugsmidjan/qj/classUtils';
4
+ import { DEFAULT_LANG } from '@reykjavik/hanna-utils/i18n.js';
4
5
  import { useDomid } from '../utils/useDomid.js';
6
+ const defaultReqText = {
7
+ is: 'Þarf að haka í',
8
+ en: 'Must be checked',
9
+ pl: 'Należy sprawdzić',
10
+ };
5
11
  // eslint-disable-next-line complexity
6
12
  export const TogglerInput = (props) => {
7
13
  const { bem, modifier, className, label, hideLabel, invalid, errorMessage, Wrapper = 'div', required, reqText, type, id, innerWrap, wrapperProps, inputProps } = props, restInputProps = __rest(props, ["bem", "modifier", "className", "label", "hideLabel", "invalid", "errorMessage", "Wrapper", "required", "reqText", "type", "id", "innerWrap", "wrapperProps", "inputProps"]);
@@ -9,7 +15,7 @@ export const TogglerInput = (props) => {
9
15
  const errorId = errorMessage && `error${domid}`;
10
16
  const reqStar = required && reqText !== false && (React.createElement("abbr", { className: `${bem}__label__reqstar`,
11
17
  // FIXME: add mo-better i18n thinking
12
- title: `${reqText || 'Þarf að haka í'}: ` }, "*"));
18
+ title: `${reqText || defaultReqText[DEFAULT_LANG]}: ` }, "*"));
13
19
  const readOnly = restInputProps.readOnly || (inputProps || {}).readOnly;
14
20
  const labelContent = (React.createElement(React.Fragment, null,
15
21
  ' ',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reykjavik/hanna-react",
3
- "version": "0.10.119",
3
+ "version": "0.10.121",
4
4
  "author": "Reykjavík (http://www.reykjavik.is)",
5
5
  "contributors": [
6
6
  "Hugsmiðjan ehf (http://www.hugsmidjan.is)",